00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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 "Scene.h"
00029
00030 void MoleculeGraphics::create_cmdlist(void) {
00031 reset_disp_list();
00032
00033 DispCmdTriangle triangle;
00034 DispCmdCylinder cylinder;
00035 DispCmdPoint point;
00036 DispCmdLine line;
00037 DispCmdCone cone;
00038 DispCmdColorIndex color;
00039 DispCmdLineType linetype;
00040 DispCmdLineWidth linewidth;
00041 DispCmdSphere sphere;
00042 DispCmdSphereRes sph_res;
00043
00044 DispCmdPickPoint cmdPickPoint;
00045
00046 append(DMATERIALON);
00047 color.putdata(0, cmdList);
00048 int last_res = -1;
00049
00050 int last_line = ::SOLIDLINE;
00051 linetype.putdata(last_line, cmdList);
00052 int last_width = 1;
00053 linewidth.putdata(last_width, cmdList);
00054
00055
00056 int num = num_elements();
00057 ShapeClass *shape;
00058 for (int i=0; i<num; i++) {
00059 shape = &(shapes[i]);
00060 switch (shape->shape) {
00061 case NONE: {
00062 break;
00063 }
00064 case POINT: {
00065 append(DMATERIALOFF);
00066 point.putdata(shape->data+0, cmdList);
00067 append(DMATERIALON);
00068 break;
00069 }
00070 case PICKPOINT:
00071 cmdPickPoint.putdata(shape->data, (int)shape->data[3], cmdList);
00072 break;
00073 case LINE: {
00074 append(DMATERIALOFF);
00075 int style = int(shape->data[6]);
00076 int width = int(shape->data[7]);
00077 if (style != last_line) {
00078 linetype.putdata(style, cmdList);
00079 last_line = style;
00080 }
00081 if (width != last_width) {
00082 linewidth.putdata(width, cmdList);
00083 last_width = width;
00084 }
00085 line.putdata(shape->data+0, shape->data+3, cmdList);
00086 append(DMATERIALON);
00087 break;
00088 }
00089 case TRIANGLE: {
00090 triangle.putdata(shape->data+0, shape->data+3, shape->data+6, cmdList);
00091 break;
00092 }
00093 case TRINORM: {
00094 triangle.putdata(shape->data+0, shape->data+3 , shape->data+6,
00095 shape->data+9, shape->data+12, shape->data+15, cmdList);
00096 break;
00097 }
00098 case TRICOLOR:
00099 {
00100
00101 float colors[9];
00102 for (int i=0; i<3; i++) {
00103 int c = (int)shape->data[18+i];
00104 c = clamp_int(c, 0, MAXCOLORS-1);
00105 vec_copy(colors+3*i, scene->color_value(c));
00106 }
00107 const float *verts = shape->data+0;
00108 const float *norms = shape->data+9;
00109 int facets[3] = { 0,1,2 };
00110 DispCmdTriMesh::putdata(verts, norms, colors, 3, facets, 1, 0, cmdList);
00111 }
00112 break;
00113 case CYLINDER: {
00114 cylinder.putdata(shape->data+0, shape->data+3, shape->data[6],
00115 int(shape->data[7]),
00116 (int (shape->data[8])) ?
00117 CYLINDER_TRAILINGCAP | CYLINDER_LEADINGCAP : 0,
00118 cmdList);
00119 break;
00120 }
00121 case CONE: {
00122 cone.putdata(shape->data+0, shape->data+3, shape->data[6],
00123 shape->data[8], int(shape->data[7]), cmdList);
00124 break;
00125 }
00126 case TEXT: {
00127 append(DMATERIALOFF);
00128 DispCmdText text;
00129 DispCmdTextSize textSize;
00130 textSize.putdata(shape->data[3], cmdList);
00131 text.putdata(shape->data, shapetext[(int)shape->data[5]], shape->data[4], cmdList);
00132 append(DMATERIALON);
00133 break;
00134 }
00135 #if 0
00136
00137 case DBEGINREPGEOMGROUP: {
00138 char *s = (char *) (shape);
00139 beginrepgeomgroup.putdata(s,cmdList);
00140 break;
00141 }
00142 case DCOMMENT: {
00143 char *s = (char *) (shape);
00144 comment.putdata(s,cmdList);
00145 break;
00146 }
00147 #endif
00148 case SPHERE: {
00149 int res = int (shape->data[4]);
00150 if (res != last_res) {
00151 sph_res.putdata(res, cmdList);
00152 last_res = res;
00153 }
00154 sphere.putdata(shape->data+0, shape->data[3], cmdList);
00155 break;
00156 }
00157 case MATERIALS: {
00158 if (shape->data[0] == 0) append(DMATERIALOFF);
00159 else append(DMATERIALON);
00160 break;
00161 }
00162 case MATERIAL: {
00163 const float *data = shape->data;
00164 cmdList->ambient = data[0];
00165 cmdList->specular = data[1];
00166 cmdList->diffuse = data[2];
00167 cmdList->shininess = data[3];
00168 cmdList->opacity = data[4];
00169 cmdList->outline = data[5];
00170 cmdList->outlinewidth = data[6];
00171 cmdList->transmode = data[7];
00172 cmdList->materialtag = (int)data[8];
00173 break;
00174 }
00175 case COLOR: {
00176 color.putdata(int(shape->data[0]), cmdList);
00177 break;
00178 }
00179 default:
00180 msgErr << "Sorry, can't draw that" << sendmsg;
00181 }
00182 }
00183 needRegenerate = 0;
00184 }
00185
00186
00187
00188
00189 int MoleculeGraphics::added(void) {
00190 needRegenerate = 1;
00191 next_index = shapes.num();
00192 int retval = next_id;
00193 if (next_id == max_id) {
00194 max_id++;
00195 }
00196 next_id = max_id;
00197 return retval;
00198 }
00199
00200
00201 int MoleculeGraphics::add_triangle(const float *x1, const float *x2, const float *x3) {
00202
00203 ShapeClass s(TRIANGLE, 9, next_id);
00204 float *data = s.data;
00205 vec_copy(data+0, x1);
00206 vec_copy(data+3, x2);
00207 vec_copy(data+6, x3);
00208
00209
00210 if (next_index < num_elements())
00211 shapes[next_index] = s;
00212 else
00213 shapes.append(s);
00214 return added();
00215 }
00216
00217
00218 int MoleculeGraphics::add_trinorm(const float *x1, const float *x2, const float *x3,
00219 const float *n1, const float *n2, const float *n3) {
00220
00221 ShapeClass s(TRINORM, 18, next_id);
00222 float *data = s.data;
00223 vec_copy(data+ 0, x1);
00224 vec_copy(data+ 3, x2);
00225 vec_copy(data+ 6, x3);
00226
00227 vec_copy(data+ 9, n1);
00228 vec_normalize(data+ 9);
00229 vec_copy(data+12, n2);
00230 vec_normalize(data+12);
00231 vec_copy(data+15, n3);
00232 vec_normalize(data+15);
00233
00234
00235 if (next_index < num_elements())
00236 shapes[next_index] = s;
00237 else
00238 shapes.append(s);
00239
00240 return added();
00241 }
00242
00243
00244 int MoleculeGraphics::add_tricolor(const float *x1, const float *x2, const float *x3,
00245 const float *n1, const float *n2, const float *n3, int c1, int c2,
00246 int c3) {
00247 ShapeClass s(TRICOLOR, 21, next_id);
00248 float *data = s.data;
00249 vec_copy(data+ 0, x1);
00250 vec_copy(data+ 3, x2);
00251 vec_copy(data+ 6, x3);
00252
00253 vec_copy(data+ 9, n1);
00254 vec_normalize(data+ 9);
00255 vec_copy(data+12, n2);
00256 vec_normalize(data+12);
00257 vec_copy(data+15, n3);
00258 vec_normalize(data+15);
00259
00260 data[18] = (float)c1;
00261 data[19] = (float)c2;
00262 data[20] = (float)c3;
00263
00264
00265 if (next_index < num_elements())
00266 shapes[next_index] = s;
00267 else
00268 shapes.append(s);
00269
00270 return added();
00271 }
00272
00273
00274 int MoleculeGraphics::add_point(const float *x) {
00275 ShapeClass s(POINT, 3, next_id);
00276 float *data = s.data;
00277 vec_copy(data+0, x);
00278
00279 if (next_index < num_elements())
00280 shapes[next_index] = s;
00281 else
00282 shapes.append(s);
00283
00284 return added();
00285 }
00286
00287 int MoleculeGraphics::add_pickpoint(const float *x) {
00288 ShapeClass s(PICKPOINT, 4, next_id);
00289 float *data = s.data;
00290 vec_copy(data+0, x);
00291 data[3] = (float) next_index;
00292
00293 if (next_index < num_elements())
00294 shapes[next_index] = s;
00295 else
00296 shapes.append(s);
00297
00298 return added();
00299 }
00300
00301 int MoleculeGraphics::add_line(const float *x1, const float *x2, int style, int width) {
00302 ShapeClass s(LINE, 8, next_id);
00303 float *data = s.data;
00304 vec_copy(data+0, x1);
00305 vec_copy(data+3, x2);
00306 data[6] = float(style) + 0.1f;
00307 data[7] = float(width) + 0.1f;
00308 if (next_index < num_elements())
00309 shapes[next_index] = s;
00310 else
00311 shapes.append(s);
00312 return added();
00313 }
00314
00315
00316 int MoleculeGraphics::add_cylinder(const float *x1, const float *x2, float rad,
00317 int n, int filled) {
00318 ShapeClass s(CYLINDER, 9, next_id);
00319 float *data = s.data;
00320 vec_copy(data+0, x1);
00321 vec_copy(data+3, x2);
00322 data[6] = rad;
00323 data[7] = float(n) + 0.1f;
00324 data[8] = float(filled) + 0.1f;
00325
00326
00327 if (next_index < num_elements())
00328 shapes[next_index] = s;
00329 else
00330 shapes.append(s);
00331 return added();
00332 }
00333
00334
00335 int MoleculeGraphics::add_cone(const float *x1, const float *x2, float rad, float radsq, int n) {
00336
00337 ShapeClass s(CONE, 9, next_id);
00338 float *data = s.data;
00339 vec_copy(data+0, x1);
00340 vec_copy(data+3, x2);
00341 data[6] = rad;
00342 data[7] = float(n) + 0.1f;
00343 data[8] = radsq;
00344
00345
00346 if (next_index < num_elements())
00347 shapes[next_index] = s;
00348 else
00349 shapes.append(s);
00350 return added();
00351 }
00352
00353
00354 int MoleculeGraphics::add_sphere(const float *x, float rad, int n) {
00355 ShapeClass s(SPHERE, 5, next_id);
00356 float *data = s.data;
00357 vec_copy(data+0, x);
00358 data[3] = rad;
00359 data[4] = float(n) + 0.1f;
00360
00361
00362 if (next_index < num_elements())
00363 shapes[next_index] = s;
00364 else
00365 shapes.append(s);
00366 return added();
00367 }
00368
00369
00370 int MoleculeGraphics::add_text(const float *x, const char *text,
00371 float size, float thickness) {
00372 ShapeClass s(TEXT, 6, next_id);
00373 float *data = s.data;
00374 vec_copy(data+0, x);
00375 data[3] = size;
00376 data[4] = thickness;
00377 data[5] = (float)shapetext.num();
00378 shapetext.append(stringdup(text));
00379 if (next_index < num_elements())
00380 shapes[next_index] = s;
00381 else
00382 shapes.append(s);
00383 return added();
00384 }
00385
00386
00387 int MoleculeGraphics::use_materials(int yes_no) {
00388 ShapeClass s(MATERIALS, 1, next_id);
00389 float *data = s.data;
00390 data[0] = (float) yes_no;
00391 if (next_index < num_elements())
00392 shapes[next_index] = s;
00393 else
00394 shapes.append(s);
00395 return added();
00396 }
00397
00398
00399 int MoleculeGraphics::use_material(const Material *mat) {
00400 ShapeClass s(MATERIAL, 9, next_id);
00401 float *data = s.data;
00402 data[0] = mat->ambient;
00403 data[1] = mat->specular;
00404 data[2] = mat->diffuse;
00405 data[3] = mat->shininess;
00406 data[4] = mat->opacity;
00407 data[5] = mat->outline;
00408 data[6] = mat->outlinewidth;
00409 data[7] = mat->transmode;
00410 data[8] = (float)mat->ind;
00411
00412 if (next_index < num_elements())
00413 shapes[next_index] = s;
00414 else
00415 shapes.append(s);
00416 return added();
00417 }
00418
00419
00420
00421 int MoleculeGraphics::use_color(int index) {
00422 ShapeClass s(COLOR, 1, next_id);
00423 float *data = s.data;
00424 data[0] = float(index) + 0.1f;
00425 if (next_index < num_elements())
00426 shapes[next_index] = s;
00427 else
00428 shapes.append(s);
00429 return added();
00430 }
00431
00432
00433
00434 int MoleculeGraphics::index_id(int find_id) {
00435
00436
00437 int max_loc = num_elements()-1;
00438 int min_loc = 0;
00439 if (max_loc < min_loc) {
00440 return -1;
00441 }
00442 int loc = (max_loc + min_loc) / 2;
00443 int id = shapes[loc].id;
00444 while (id != find_id && min_loc < max_loc) {
00445 if (id < find_id) {
00446 min_loc = loc+1;
00447 } else {
00448 max_loc = loc-1;
00449 }
00450 loc = (max_loc + min_loc) / 2;
00451 if (loc < 0) break;
00452 id = shapes[loc].id;
00453 }
00454
00455 if (id == find_id && shapes[loc].shape != NONE) {
00456 return loc;
00457 }
00458 return -1;
00459 }
00460
00461
00462
00463 void MoleculeGraphics::delete_all(void) {
00464 shapes.clear();
00465 delete_shapetext();
00466 delete_count = 0;
00467 next_index = 0;
00468 next_id = 0;
00469 max_id = 0;
00470 needRegenerate = 1;
00471 }
00472
00473
00474
00475 void MoleculeGraphics::delete_id(int id) {
00476 int index = index_id(id);
00477 if (index < 0) return;
00478 shapes[index].clear();
00479 delete_count++;
00480 if (delete_count > 1
00481 ) {
00482
00483 int i, j=0, n = num_elements();
00484
00485 for (i=0; i<n; i++) {
00486 if (shapes[i].shape != NONE) {
00487 if (i != j) {
00488 shapes[j] = shapes[i];
00489 }
00490 j++;
00491 }
00492 }
00493 i=j;
00494 while (i<n) {
00495 shapes[i].clear();
00496 i++;
00497 }
00498
00499 for (int k=n-1; k >= j; k--) shapes.remove(k);
00500 delete_count = 0;
00501 }
00502 needRegenerate = 1;
00503
00504 next_id = max_id;
00505 next_index = num_elements();
00506 }
00507
00508
00509
00510
00511 int MoleculeGraphics::replace_id(int id) {
00512 int index = index_id(id);
00513 if (index < 0) return -1;
00514
00515
00516 if (next_id != max_id) {
00517 delete_count++;
00518 }
00519
00520 shapes[index].clear();
00521 next_id = id;
00522 next_index = index;
00523 return index;
00524 }
00525
00526
00527 const char *MoleculeGraphics::info_id(int id) {
00528 int index = index_id(id);
00529 if (index < 0) return NULL;
00530 ShapeClass *shape;
00531 shape = &(shapes[index]);
00532 if (!shape->data) {
00533 msgErr << "NULL data for a shape in MoleculeGraphics.C" << sendmsg;
00534 return "";
00535 }
00536 switch (shape->shape) {
00537 case NONE: {
00538 graphics_info[0] = '\0';
00539 return graphics_info;
00540 }
00541 case POINT: {
00542 sprintf(graphics_info, "point {%f %f %f}",
00543 shape->data[0], shape->data[1], shape->data[2]);
00544 return graphics_info;
00545 }
00546 case PICKPOINT: {
00547 sprintf(graphics_info, "pickpoint {%f %f %f} %d",
00548 shape->data[0], shape->data[1], shape->data[2], (int)shape->data[3]);
00549 return graphics_info;
00550 }
00551 case LINE: {
00552 sprintf(graphics_info, "line {%f %f %f} {%f %f %f} style %s width %d",
00553 shape->data[0], shape->data[1], shape->data[2],
00554 shape->data[3], shape->data[4], shape->data[5],
00555 shape->data[6] < 0.5 ? "solid" : "dashed",
00556 int(shape->data[7]));
00557 return graphics_info;
00558 }
00559 case TRIANGLE: {
00560 sprintf(graphics_info, "triangle {%f %f %f} {%f %f %f} {%f %f %f}",
00561 shape->data[0], shape->data[1], shape->data[2],
00562 shape->data[3], shape->data[4], shape->data[5],
00563 shape->data[6], shape->data[7], shape->data[8]);
00564 return graphics_info;
00565 }
00566 case TRINORM: {
00567 sprintf(graphics_info, "trinorm {%f %f %f} {%f %f %f} {%f %f %f} "
00568 "{%f %f %f} {%f %f %f} {%f %f %f}",
00569 shape->data[0], shape->data[1], shape->data[2],
00570 shape->data[3], shape->data[4], shape->data[5],
00571 shape->data[6], shape->data[7], shape->data[8],
00572 shape->data[9], shape->data[10], shape->data[11],
00573 shape->data[12], shape->data[13], shape->data[14],
00574 shape->data[15], shape->data[16], shape->data[17]);
00575 return graphics_info;
00576 }
00577 case TRICOLOR: {
00578 sprintf(graphics_info, "tricolor {%f %f %f} {%f %f %f} {%f %f %f} "
00579 "{%f %f %f} {%f %f %f} {%f %f %f} %d %d %d",
00580 shape->data[0], shape->data[1], shape->data[2],
00581 shape->data[3], shape->data[4], shape->data[5],
00582 shape->data[6], shape->data[7], shape->data[8],
00583 shape->data[9], shape->data[10], shape->data[11],
00584 shape->data[12], shape->data[13], shape->data[14],
00585 shape->data[15], shape->data[16], shape->data[17],
00586 (int)shape->data[18], (int)shape->data[19], (int)shape->data[20]);
00587 return graphics_info;
00588 }
00589 case CYLINDER: {
00590 sprintf(graphics_info, "cylinder {%f %f %f} {%f %f %f} "
00591 "radius %f resolution %d filled %d",
00592 shape->data[0], shape->data[1], shape->data[2],
00593 shape->data[3], shape->data[4], shape->data[5],
00594 shape->data[6], int(shape->data[7]), int(shape->data[8]));
00595 return graphics_info;
00596 }
00597 case CONE: {
00598 sprintf(graphics_info, "cone {%f %f %f} {%f %f %f} "
00599 "radius %f radius2 %f resolution %d",
00600 shape->data[0], shape->data[1], shape->data[2],
00601 shape->data[3], shape->data[4], shape->data[5],
00602 shape->data[6], shape->data[8], int(shape->data[7]));
00603 return graphics_info;
00604 }
00605 case SPHERE: {
00606 sprintf(graphics_info, "sphere {%f %f %f} radius %f resolution %d",
00607 shape->data[0], shape->data[1], shape->data[2],
00608 shape->data[3], int(shape->data[4]));
00609 return graphics_info;
00610 }
00611 case TEXT: {
00612 sprintf(graphics_info, "text {%f %f %f} {%s} size %f thickness %f",
00613 shape->data[0], shape->data[1], shape->data[2],
00614 shapetext[(int)shape->data[5]], shape->data[3], shape->data[4]);
00615 return graphics_info;
00616 }
00617 case MATERIALS: {
00618 sprintf(graphics_info, "materials %d", int(shape->data[0]));
00619 return graphics_info;
00620 }
00621 case MATERIAL: {
00622 sprintf(graphics_info, "material %d", int(shape->data[8]));
00623 return graphics_info;
00624 }
00625 case COLOR: {
00626 sprintf(graphics_info, "color %d", int(shape->data[0]));
00627 return graphics_info;
00628 }
00629 default:
00630 return "";
00631 }
00632 }
00633
00634
00635
00636 #define CHECK_RANGE(v) \
00637 { \
00638 if (!found_one) { \
00639 found_one = 1; \
00640 minx = maxx = (v)[0]; \
00641 miny = maxy = (v)[1]; \
00642 minz = maxz = (v)[2]; \
00643 } else { \
00644 if (minx > (v)[0]) minx = (v)[0]; if (maxx < (v)[0]) maxx = (v)[0]; \
00645 if (miny > (v)[1]) miny = (v)[1]; if (maxy < (v)[1]) maxy = (v)[1]; \
00646 if (minz > (v)[2]) minz = (v)[2]; if (maxz < (v)[2]) maxz = (v)[2]; \
00647 } \
00648 }
00649
00650
00651 void MoleculeGraphics::find_sizes(void) {
00652 float minx=0.0f, maxx=0.0f;
00653 float miny=0.0f, maxy=0.0f;
00654 float minz=0.0f, maxz=0.0f;
00655 int found_one = 0;
00656
00657 int num = num_elements();
00658 ShapeClass *shape;
00659 for (int i=0; i<num; i++) {
00660 shape = &(shapes[i]);
00661 switch (shape->shape) {
00662 case NONE: {
00663 break;
00664 }
00665 case POINT: {
00666 CHECK_RANGE(shape->data+0);
00667 break;
00668 }
00669 case PICKPOINT: {
00670 CHECK_RANGE(shape->data+0);
00671 break;
00672 }
00673 case LINE: {
00674 CHECK_RANGE(shape->data+0);
00675 CHECK_RANGE(shape->data+3);
00676 break;
00677 }
00678 case TRIANGLE: {
00679 CHECK_RANGE(shape->data+0);
00680 CHECK_RANGE(shape->data+3);
00681 CHECK_RANGE(shape->data+6);
00682 break;
00683 }
00684 case TRINORM: {
00685 CHECK_RANGE(shape->data+0);
00686 CHECK_RANGE(shape->data+3);
00687 CHECK_RANGE(shape->data+6);
00688 break;
00689 }
00690 case TRICOLOR: {
00691 CHECK_RANGE(shape->data+0);
00692 CHECK_RANGE(shape->data+3);
00693 CHECK_RANGE(shape->data+6);
00694 break;
00695 }
00696 case CYLINDER: {
00697 CHECK_RANGE(shape->data+0);
00698 CHECK_RANGE(shape->data+3);
00699 break;
00700 }
00701 case CONE: {
00702 CHECK_RANGE(shape->data+0);
00703 CHECK_RANGE(shape->data+3);
00704 break;
00705 }
00706 case SPHERE: {
00707 CHECK_RANGE(shape->data+0);
00708 break;
00709 }
00710 case TEXT: {
00711 CHECK_RANGE(shape->data+0);
00712 break;
00713 }
00714 default:
00715 break;
00716 }
00717 }
00718
00719
00720 if (!found_one) {
00721 cov_pos[0] = cov_pos[1] = cov_pos[2];
00722 cov_scale = 0.1f;
00723 } else {
00724 cov_pos[0] = (minx + maxx) / 2.0f;
00725 cov_pos[1] = (miny + maxy) / 2.0f;
00726 cov_pos[2] = (minz + maxz) / 2.0f;
00727 float dx = maxx - minx;
00728 float dy = maxy - miny;
00729 float dz = maxz - minz;
00730
00731 if (dx == 0 && dy == 0 && dz == 0) dx = 10;
00732 if (dx > dy) {
00733 if (dx > dz) {
00734 cov_scale = 2.0f / dx;
00735 } else {
00736 cov_scale = 2.0f / dz;
00737 }
00738 } else {
00739 if (dy > dz) {
00740 cov_scale = 2.0f / dy;
00741 } else {
00742 cov_scale = 2.0f / dz;
00743 }
00744 }
00745 }
00746 }
00747
00748
00749 void MoleculeGraphics::delete_shapetext() {
00750 for (int i=0; i<shapetext.num(); i++)
00751 delete [] shapetext[i];
00752
00753 shapetext.clear();
00754 }
00755