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

DrawMolItemVolume.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2009 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: DrawMolItemVolume.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.145 $      $Date: 2009/11/05 22:29:18 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *   A continuation of rendering types from DrawMolItem
00019  *
00020  *   This file only contains representations for visualizing volumetric data
00021  ***************************************************************************/
00022 
00023 #include <math.h>
00024 #include <stdlib.h>
00025 #include <stdio.h>
00026 
00027 #include "DrawMolItem.h"
00028 #include "DrawMolecule.h"
00029 #include "BaseMolecule.h" // need volume data definitions
00030 #include "Inform.h"
00031 #include "Isosurface.h"
00032 #include "MoleculeList.h"
00033 #include "Scene.h"
00034 #include "VolumetricData.h"
00035 #include "VMDApp.h"
00036 #include "WKFUtils.h"
00037 
00038 #define MYSGN(a) (((a) > 0) ? 1 : -1)
00039 
00040 int DrawMolItem::draw_volume_get_colorid(void) {
00041   int colorid = 0;
00042   int catindex;
00043 
00044   switch (atomColor->method()) {
00045     case AtomColor::MOLECULE:
00046     case AtomColor::COLORID:
00047       colorid = atomColor->color_index();
00048       break;
00049 
00050     default:
00051       catindex = scene->category_index("Display");
00052       colorid = scene->category_item_value(catindex, "Foreground"); 
00053       break;
00054   }
00055 
00056   return colorid;
00057 }
00058 
00059 
00060 void DrawMolItem::draw_volume_box_solid(const VolumetricData * v) {
00061   float v0[3], v1[3], v2[3];
00062   float vorigin[3], vxaxis[3], vyaxis[3], vzaxis[3];
00063   int usecolor;
00064 
00065   int i;
00066   for (i=0; i<3; i++) {
00067     vorigin[i] = float(v->origin[i]);
00068     vxaxis[i] = float(v->xaxis[i]);
00069     vyaxis[i] = float(v->yaxis[i]);
00070     vzaxis[i] = float(v->zaxis[i]);
00071   }
00072 
00073   append(DMATERIALON); // enable lighting and shading
00074   usecolor=draw_volume_get_colorid();
00075   cmdColorIndex.putdata(usecolor, cmdList);
00076 
00077   // Draw XY plane
00078   v0[0] = vorigin[0];
00079   v0[1] = vorigin[1];
00080   v0[2] = vorigin[2];
00081 
00082   v1[0] = v0[0] + vxaxis[0]; 
00083   v1[1] = v0[1] + vxaxis[1]; 
00084   v1[2] = v0[2] + vxaxis[2]; 
00085 
00086   v2[0] = v1[0] + vyaxis[0];
00087   v2[1] = v1[1] + vyaxis[1];
00088   v2[2] = v1[2] + vyaxis[2];
00089   cmdSquare.putdata(v2, v1, v0, cmdList);
00090 
00091   // Draw XZ plane
00092   v2[0] = v1[0] + vzaxis[0];
00093   v2[1] = v1[1] + vzaxis[1];
00094   v2[2] = v1[2] + vzaxis[2];
00095   cmdSquare.putdata(v0, v1, v2, cmdList);
00096 
00097   // Draw YZ plane
00098   v1[0] = v0[0] + vyaxis[0]; 
00099   v1[1] = v0[1] + vyaxis[1]; 
00100   v1[2] = v0[2] + vyaxis[2]; 
00101 
00102   v2[0] = v1[0] + vzaxis[0];
00103   v2[1] = v1[1] + vzaxis[1];
00104   v2[2] = v1[2] + vzaxis[2];
00105   cmdSquare.putdata(v2, v1, v0, cmdList);
00106 
00107   // Draw XY +Z plane
00108   v0[0] = vorigin[0] + vzaxis[0];
00109   v0[1] = vorigin[1] + vzaxis[1];
00110   v0[2] = vorigin[2] + vzaxis[2];
00111 
00112   v1[0] = v0[0] + vxaxis[0]; 
00113   v1[1] = v0[1] + vxaxis[1]; 
00114   v1[2] = v0[2] + vxaxis[2]; 
00115 
00116   v2[0] = v1[0] + vyaxis[0];
00117   v2[1] = v1[1] + vyaxis[1];
00118   v2[2] = v1[2] + vyaxis[2];
00119   cmdSquare.putdata(v0, v1, v2, cmdList);
00120 
00121   // Draw XZ +Y plane
00122   v0[0] = vorigin[0] + vyaxis[0];
00123   v0[1] = vorigin[1] + vyaxis[1];
00124   v0[2] = vorigin[2] + vyaxis[2];
00125 
00126   v1[0] = v0[0] + vxaxis[0]; 
00127   v1[1] = v0[1] + vxaxis[1]; 
00128   v1[2] = v0[2] + vxaxis[2]; 
00129 
00130   v2[0] = v1[0] + vzaxis[0];
00131   v2[1] = v1[1] + vzaxis[1];
00132   v2[2] = v1[2] + vzaxis[2];
00133   cmdSquare.putdata(v2, v1, v0, cmdList);
00134 
00135   // Draw YZ +X plane
00136   v0[0] = vorigin[0] + vxaxis[0];
00137   v0[1] = vorigin[1] + vxaxis[1];
00138   v0[2] = vorigin[2] + vxaxis[2];
00139 
00140   v1[0] = v0[0] + vyaxis[0]; 
00141   v1[1] = v0[1] + vyaxis[1]; 
00142   v1[2] = v0[2] + vyaxis[2]; 
00143 
00144   v2[0] = v1[0] + vzaxis[0];
00145   v2[1] = v1[1] + vzaxis[1];
00146   v2[2] = v1[2] + vzaxis[2];
00147   cmdSquare.putdata(v0, v1, v2, cmdList);
00148 
00149   draw_volume_box_lines(v);
00150 }
00151 
00152 void DrawMolItem::draw_volume_box_lines(const VolumetricData * v) {
00153   float start[3], end[3];
00154   int xaxiscolor, yaxiscolor, zaxiscolor, axiscolor;
00155   int catindex;
00156   float vorigin[3], vxaxis[3], vyaxis[3], vzaxis[3];
00157 
00158   int i;
00159   for (i=0; i<3; i++) {
00160     vorigin[i] = float(v->origin[i]);
00161     vxaxis[i] = float(v->xaxis[i]);
00162     vyaxis[i] = float(v->yaxis[i]);
00163     vzaxis[i] = float(v->zaxis[i]);
00164   }
00165 
00166   // get colors from the scene pointer
00167   catindex = scene->category_index("Axes");
00168   xaxiscolor = scene->category_item_value(catindex, "X"); 
00169   yaxiscolor = scene->category_item_value(catindex, "Y"); 
00170   zaxiscolor = scene->category_item_value(catindex, "Z"); 
00171 
00172   catindex = scene->category_index("Display");
00173   axiscolor = scene->category_item_value(catindex, "Foreground"); 
00174  
00175   append(DMATERIALOFF);
00176   cmdLineType.putdata(SOLIDLINE, cmdList);
00177   cmdLineWidth.putdata(3, cmdList);
00178 
00179   start[0] = vorigin[0];
00180   start[1] = vorigin[1];
00181   start[2] = vorigin[2];
00182 
00183   // Draw X axis of volume box
00184   cmdColorIndex.putdata(xaxiscolor, cmdList);
00185   end[0] = start[0] + vxaxis[0];
00186   end[1] = start[1] + vxaxis[1];
00187   end[2] = start[2] + vxaxis[2];
00188   cmdLine.putdata(start, end, cmdList);
00189 
00190   // Draw Y axis of volume box
00191   cmdColorIndex.putdata(yaxiscolor, cmdList);
00192   end[0] = start[0] + vyaxis[0];
00193   end[1] = start[1] + vyaxis[1];
00194   end[2] = start[2] + vyaxis[2];
00195   cmdLine.putdata(start, end, cmdList);
00196 
00197   // Draw Z axis of volume box
00198   cmdColorIndex.putdata(zaxiscolor, cmdList);
00199   end[0] = start[0] + vzaxis[0];
00200   end[1] = start[1] + vzaxis[1];
00201   end[2] = start[2] + vzaxis[2];
00202   cmdLine.putdata(start, end, cmdList);
00203 
00204   // Draw remaining outline of volume box
00205   cmdLineWidth.putdata(1, cmdList);
00206   cmdColorIndex.putdata(axiscolor, cmdList);
00207  
00208   start[0] = vorigin[0] + vxaxis[0];    
00209   start[1] = vorigin[1] + vxaxis[1];    
00210   start[2] = vorigin[2] + vxaxis[2];    
00211 
00212   end[0] = start[0] + vyaxis[0];
00213   end[1] = start[1] + vyaxis[1];
00214   end[2] = start[2] + vyaxis[2];
00215   cmdLine.putdata(start, end, cmdList);
00216 
00217   end[0] = start[0] + vzaxis[0];
00218   end[1] = start[1] + vzaxis[1];
00219   end[2] = start[2] + vzaxis[2];
00220   cmdLine.putdata(start, end, cmdList);
00221 
00222   start[0] = vorigin[0] + vyaxis[0];    
00223   start[1] = vorigin[1] + vyaxis[1];    
00224   start[2] = vorigin[2] + vyaxis[2];    
00225 
00226   end[0] = start[0] + vxaxis[0];
00227   end[1] = start[1] + vxaxis[1];
00228   end[2] = start[2] + vxaxis[2];
00229   cmdLine.putdata(start, end, cmdList);
00230 
00231   end[0] = start[0] + vzaxis[0];
00232   end[1] = start[1] + vzaxis[1];
00233   end[2] = start[2] + vzaxis[2];
00234   cmdLine.putdata(start, end, cmdList);
00235 
00236 
00237   start[0] = vorigin[0] + vzaxis[0];    
00238   start[1] = vorigin[1] + vzaxis[1];    
00239   start[2] = vorigin[2] + vzaxis[2];    
00240 
00241   end[0] = start[0] + vxaxis[0];
00242   end[1] = start[1] + vxaxis[1];
00243   end[2] = start[2] + vxaxis[2];
00244   cmdLine.putdata(start, end, cmdList);
00245 
00246   end[0] = start[0] + vyaxis[0];
00247   end[1] = start[1] + vyaxis[1];
00248   end[2] = start[2] + vyaxis[2];
00249   cmdLine.putdata(start, end, cmdList);
00250  
00251 
00252   start[0] = vorigin[0] + vxaxis[0] + vyaxis[0] + vzaxis[0];
00253   start[1] = vorigin[1] + vxaxis[1] + vyaxis[1] + vzaxis[1];
00254   start[2] = vorigin[2] + vxaxis[2] + vyaxis[2] + vzaxis[2];
00255  
00256   end[0] = start[0] - vxaxis[0];
00257   end[1] = start[1] - vxaxis[1];
00258   end[2] = start[2] - vxaxis[2];
00259   cmdLine.putdata(start, end, cmdList);
00260 
00261   end[0] = start[0] - vyaxis[0];
00262   end[1] = start[1] - vyaxis[1];
00263   end[2] = start[2] - vyaxis[2];
00264   cmdLine.putdata(start, end, cmdList);
00265 
00266   end[0] = start[0] - vzaxis[0];
00267   end[1] = start[1] - vzaxis[1];
00268   end[2] = start[2] - vzaxis[2];
00269   cmdLine.putdata(start, end, cmdList);
00270 }
00271 
00272 
00273 void DrawMolItem::draw_volume_isosurface_points(const VolumetricData * v,
00274                                 float isovalue, int stepsize, int thickness) {
00275   int x,y,z;
00276   float *addr;
00277   float pos[3];
00278   float xax[3], yax[3], zax[3];
00279   int pointcount = 0;
00280   int usecolor;
00281   ResizeArray<float> centers;
00282   ResizeArray<float> colors;
00283 
00284   int i;
00285   float vorigin[3];
00286   for (i=0; i<3; i++) {
00287     vorigin[i] = float(v->origin[i]);
00288   }
00289   
00290   append(DMATERIALOFF);
00291   usecolor = draw_volume_get_colorid();
00292   const float *cp = scene->color_value(usecolor);
00293   cmdColorIndex.putdata(usecolor, cmdList);
00294 
00295   // calculate cell axes
00296   v->cell_axes(xax, yax, zax);
00297 
00298   for (z=0; z<v->zsize; z+=stepsize) {
00299     for (y=0; y<v->ysize; y+=stepsize) {
00300       addr = &(v->data[(z * (v->xsize * v->ysize)) + (y * v->xsize)]);  
00301 
00302       // loop through xsize - 1 rather than the full range
00303       for (x=0; x<(v->xsize - 1); x+=stepsize) {
00304         float diff, isodiff;
00305       
00306         // draw a point if the isovalue falls between neighboring X samples
00307         diff    = addr[x] - addr[x+1];
00308         isodiff = addr[x] - isovalue;
00309         if ((fabs(diff) > fabs(isodiff)) && (MYSGN(diff) == MYSGN(isodiff))) { 
00310           pos[0] = vorigin[0] + x * xax[0] + y * yax[0] + z * zax[0];
00311           pos[1] = vorigin[1] + x * xax[1] + y * yax[1] + z * zax[1];
00312           pos[2] = vorigin[2] + x * xax[2] + y * yax[2] + z * zax[2];
00313 
00314           // draw a point there.
00315           centers.append(pos[0]);
00316           centers.append(pos[1]);
00317           centers.append(pos[2]);
00318           colors.append(cp[0]);
00319           colors.append(cp[1]);
00320           colors.append(cp[2]);
00321 
00322           pointcount++;
00323         }
00324       } 
00325     } 
00326   }
00327 
00328   if (pointcount > 0) {
00329     cmdPointArray.putdata((float *) &centers[0],
00330                           (float *) &colors[0],
00331                           (float) thickness,
00332                           pointcount,
00333                           cmdList);
00334   }
00335 }
00336 
00337 
00338 void DrawMolItem::draw_volume_isosurface_lit_points(const VolumetricData * v, 
00339                                  float isovalue, int stepsize, int thickness) {
00340   int x,y,z;
00341   float *addr;
00342   float pos[3];
00343   float xax[3], yax[3], zax[3];
00344   ResizeArray<float> centers;
00345   ResizeArray<float> normals;
00346   ResizeArray<float> colors;
00347 
00348   int i;
00349   float vorigin[3];
00350   for (i=0; i<3; i++) {
00351     vorigin[i] = float(v->origin[i]);
00352   }
00353 
00354   int pointcount = 0;
00355   int usecolor;
00356   append(DMATERIALON);
00357   usecolor = draw_volume_get_colorid();
00358   const float *cp = scene->color_value(usecolor);
00359   cmdColorIndex.putdata(usecolor, cmdList);
00360 
00361   // calculate cell axes
00362   v->cell_axes(xax, yax, zax);
00363 
00364   for (z=0; z<v->zsize; z+=stepsize) {
00365     for (y=0; y<v->ysize; y+=stepsize) {
00366       addr = &(v->data[(z * (v->xsize * v->ysize)) + (y * v->xsize)]);  
00367 
00368       // loop through xsize - 1 rather than the full range
00369       for (x=0; x<(v->xsize - 1); x+=stepsize) {
00370         float diff, isodiff;
00371       
00372         // draw a point if the isovalue falls between neighboring X samples
00373         diff    = addr[x] - addr[x+1];
00374         isodiff = addr[x] - isovalue;
00375         if ((fabs(diff) > fabs(isodiff)) && (MYSGN(diff) == MYSGN(isodiff))) { 
00376           pos[0] = vorigin[0] + x * xax[0] + y * yax[0] + z * zax[0];
00377           pos[1] = vorigin[1] + x * xax[1] + y * yax[1] + z * zax[1];
00378           pos[2] = vorigin[2] + x * xax[2] + y * yax[2] + z * zax[2];
00379 
00380           float norm[3];
00381           vec_copy(norm, &v->gradient[(z*v->xsize*v->ysize + y*v->xsize + x) * 3]);
00382  
00383           // draw a point there.
00384           centers.append(pos[0]);
00385           centers.append(pos[1]);
00386           centers.append(pos[2]);
00387           normals.append(norm[0]);
00388           normals.append(norm[1]);
00389           normals.append(norm[2]);
00390           colors.append(cp[0]);
00391           colors.append(cp[1]);
00392           colors.append(cp[2]);
00393 
00394           pointcount++;
00395         }
00396       } 
00397     } 
00398   }
00399 
00400   if (pointcount > 0) {
00401     DispCmdLitPointArray cmdLitPointArray;
00402     cmdLitPointArray.putdata((float *) &centers[0],
00403                              (float *) &normals[0],
00404                              (float *) &colors[0],
00405                              (float) thickness,
00406                              pointcount,
00407                              cmdList);
00408   }
00409 }
00410 
00411 
00412 void DrawMolItem::draw_volume_isosurface_lines(const VolumetricData * v, 
00413                                  float isovalue, int stepsize, int thickness) {
00414   int i, usecolor;
00415   IsoSurface *s = new IsoSurface;
00416   s->clear();
00417   s->compute(v, isovalue, stepsize);
00418 
00419   if (s->numtriangles > 0) {
00420     append(DMATERIALOFF); // enable lighting and shading
00421     cmdLineType.putdata(SOLIDLINE, cmdList);
00422     cmdLineWidth.putdata(thickness, cmdList);
00423 
00424     usecolor = draw_volume_get_colorid();
00425     cmdColorIndex.putdata(usecolor, cmdList);
00426 
00427     // draw triangles
00428     for (i=0; i<s->numtriangles; i++) {
00429       float *addr;
00430       addr = &(s->v[i * 9]); 
00431       cmdLine.putdata(&addr[0], &addr[3], cmdList);
00432       cmdLine.putdata(&addr[3], &addr[6], cmdList);
00433       cmdLine.putdata(&addr[6], &addr[0], cmdList);
00434     }
00435   }
00436 
00437   delete s; // we don't need this stuff after this point 
00438 }
00439 
00440 
00441 
00442 void DrawMolItem::draw_volume_isosurface_trimesh(const VolumetricData * v, 
00443                                      float isovalue, int stepsize) {
00444   int i, usecolor;
00445   IsoSurface s;
00446   s.clear();                 // initialize isosurface data
00447   s.compute(v, isovalue, stepsize); // compute the isosurface
00448   s.vertexfusion(v, 36, 36); // identify and eliminate duplicated vertices
00449   s.normalize();             // normalize interpolated gradient/surface normals
00450 
00451   if (s.numtriangles > 0) {
00452     append(DMATERIALON); // enable lighting and shading
00453     usecolor = draw_volume_get_colorid();
00454     cmdColorIndex.putdata(usecolor, cmdList);
00455 
00456     // draw surface with per-vertex normals using a vertex array
00457     float *c = new float[s.numtriangles * 9];
00458     const float *fp = scene->color_value(usecolor);
00459     for (i=0; i<s.numtriangles; i++) { 
00460       int ind = i * 9;
00461 
00462       c[ind    ] = fp[0]; // Red
00463       c[ind + 1] = fp[1]; // Green
00464       c[ind + 2] = fp[2]; // Blue
00465 
00466       ind+=3;
00467       c[ind    ] = fp[0]; // Red
00468       c[ind + 1] = fp[1]; // Green
00469       c[ind + 2] = fp[2]; // Blue
00470 
00471       ind+=3;
00472       c[ind    ] = fp[0]; // Red
00473       c[ind + 1] = fp[1]; // Green
00474       c[ind + 2] = fp[2]; // Blue
00475     }
00476 
00477     // Create a triangle mesh
00478     // XXX don't try to stripify it since this triggers a crash in ACTC for
00479     //     unknown reasons
00480     cmdTriMesh.putdata(&s.v[0], &s.n[0], c, s.v.num() / 3,
00481                        &s.f[0], s.numtriangles, 0, cmdList);
00482 
00483     delete [] c;
00484   }
00485 }
00486 
00487 
00488 // recompute sliceTextureCoord, sliceVertexCoord, and sliceNormal
00489 // using the given volumetric data set, axis, and offset
00490 // sliceAxis and sliceOffset.  
00491 static void prepare_texture_coordinates(const VolumetricData *v, 
00492     float loc, int axis, float *sliceNormal, float *sliceTextureCoords,
00493     float *sliceVertexes) {
00494 
00495   float t0[3], t1[3], t2[3], t3[3];
00496   float v0[3], v1[3], v2[3], v3[3];
00497   float normal[3];
00498 
00499   float vorigin[3], vxaxis[3], vyaxis[3], vzaxis[3];
00500   int i;
00501   for (i=0; i<3; i++) {
00502     vorigin[i] = float(v->origin[i]);
00503     vxaxis[i] = float(v->xaxis[i]);
00504     vyaxis[i] = float(v->yaxis[i]);
00505     vzaxis[i] = float(v->zaxis[i]);
00506   }
00507 
00508 
00509   if (loc < 0.0f)
00510       loc = 0.0f;
00511 
00512   if (loc > 1.0f)
00513       loc = 1.0f;
00514 
00515   switch (axis) {
00516     // X-Axis
00517     case 0:
00518     default:
00519       t0[0] = loc;
00520       t0[1] = 0.0f;
00521       t0[2] = 0.0f;
00522 
00523       t1[0] = loc;
00524       t1[1] = 0.0f;
00525       t1[2] = 1.0f;
00526 
00527       t2[0] = loc;
00528       t2[1] = 1.0f;
00529       t2[2] = 1.0f;
00530 
00531       t3[0] = loc;
00532       t3[1] = 1.0f;
00533       t3[2] = 0.0f;
00534 
00535       v0[0] = vorigin[0] + (vxaxis[0] * loc);
00536       v0[1] = vorigin[1] + (vxaxis[1] * loc);
00537       v0[2] = vorigin[2] + (vxaxis[2] * loc);
00538 
00539       v1[0] = v0[0] + vzaxis[0];
00540       v1[1] = v0[1] + vzaxis[1];
00541       v1[2] = v0[2] + vzaxis[2];
00542 
00543       v2[0] = v0[0] + vzaxis[0] + vyaxis[0];
00544       v2[1] = v0[1] + vzaxis[1] + vyaxis[1];
00545       v2[2] = v0[2] + vzaxis[2] + vyaxis[2];
00546 
00547       v3[0] = v0[0]             + vyaxis[0];
00548       v3[1] = v0[1]             + vyaxis[1];
00549       v3[2] = v0[2]             + vyaxis[2];
00550 
00551       normal[0] = vxaxis[0];
00552       normal[1] = vxaxis[1];
00553       normal[2] = vxaxis[2];
00554       vec_normalize(&normal[0]);
00555       break;
00556 
00557     // Y-Axis
00558     case 1:
00559       t0[0] = 0.0f;
00560       t0[1] = loc;
00561       t0[2] = 0.0f;
00562 
00563       t1[0] = 1.0f;
00564       t1[1] = loc;
00565       t1[2] = 0.0f;
00566 
00567       t2[0] = 1.0f;
00568       t2[1] = loc;
00569       t2[2] = 1.0f;
00570 
00571       t3[0] = 0.0f;
00572       t3[1] = loc;
00573       t3[2] = 1.0f;
00574 
00575       v0[0] = vorigin[0] + (vyaxis[0] * loc);
00576       v0[1] = vorigin[1] + (vyaxis[1] * loc);
00577       v0[2] = vorigin[2] + (vyaxis[2] * loc);
00578 
00579       v1[0] = v0[0] + vxaxis[0];
00580       v1[1] = v0[1] + vxaxis[1];
00581       v1[2] = v0[2] + vxaxis[2];
00582 
00583       v2[0] = v0[0] + vxaxis[0] + vzaxis[0];
00584       v2[1] = v0[1] + vxaxis[1] + vzaxis[1];
00585       v2[2] = v0[2] + vxaxis[2] + vzaxis[2];
00586 
00587       v3[0] = v0[0]             + vzaxis[0];
00588       v3[1] = v0[1]             + vzaxis[1];
00589       v3[2] = v0[2]             + vzaxis[2];
00590 
00591       normal[0] = vyaxis[0];
00592       normal[1] = vyaxis[1];
00593       normal[2] = vyaxis[2];
00594       vec_normalize(&normal[0]);
00595       break;
00596 
00597     // Z-Axis
00598     case 2:
00599       t0[0] = 0.0f;
00600       t0[1] = 0.0f;
00601       t0[2] = loc;
00602 
00603       t1[0] = 1.0f;
00604       t1[1] = 0.0f;
00605       t1[2] = loc;
00606 
00607       t2[0] = 1.0f;
00608       t2[1] = 1.0f;
00609       t2[2] = loc;
00610 
00611       t3[0] = 0.0f;
00612       t3[1] = 1.0f;
00613       t3[2] = loc;
00614 
00615       v0[0] = vorigin[0] + (vzaxis[0] * loc);
00616       v0[1] = vorigin[1] + (vzaxis[1] * loc);
00617       v0[2] = vorigin[2] + (vzaxis[2] * loc);
00618 
00619       v1[0] = v0[0] + vxaxis[0];
00620       v1[1] = v0[1] + vxaxis[1];
00621       v1[2] = v0[2] + vxaxis[2];
00622 
00623       v2[0] = v0[0] + vxaxis[0] + vyaxis[0];
00624       v2[1] = v0[1] + vxaxis[1] + vyaxis[1];
00625       v2[2] = v0[2] + vxaxis[2] + vyaxis[2];
00626 
00627       v3[0] = v0[0]             + vyaxis[0];
00628       v3[1] = v0[1]             + vyaxis[1];
00629       v3[2] = v0[2]             + vyaxis[2];
00630 
00631       normal[0] = vzaxis[0];
00632       normal[1] = vzaxis[1];
00633       normal[2] = vzaxis[2];
00634       vec_normalize(&normal[0]);
00635       break;
00636   }
00637 
00638   vec_copy(sliceTextureCoords  , t0);
00639   vec_copy(sliceTextureCoords+3, t1);
00640   vec_copy(sliceTextureCoords+6, t2);
00641   vec_copy(sliceTextureCoords+9, t3);
00642   vec_copy(sliceVertexes  , v0);
00643   vec_copy(sliceVertexes+3, v1);
00644   vec_copy(sliceVertexes+6, v2);
00645   vec_copy(sliceVertexes+9, v3);
00646   vec_copy(sliceNormal, normal);
00647 }
00648 
00649 void DrawMolItem::updateVolumeTexture() {
00650   float vmin, vmax;
00651   int volid = atomColor->volume_index();
00652   if (atomRep->method()==AtomRep::VOLSLICE) {
00653     // the volslice rep has its own volid specification
00654     volid = (int)atomRep->get_data(AtomRep::SPHERERES);
00655   }
00656 
00657   const VolumetricData *v = mol->get_volume_data(volid);
00658   if (v == NULL) {
00659     msgInfo << "No volume data loaded at index " << volid << sendmsg;
00660     return;
00661   } 
00662 
00663   // determine if a new 3D texture needs to be prepared and uploaded.  This
00664   // occurs if:
00665   // (1) the coloring method has changed
00666   // (2) the choice of volumetric data set has changed.
00667   atomColor->get_colorscale_minmax(&vmin, &vmax);
00668   if (!vmin && !vmax) {
00669     vmin = v->datamin;
00670     vmax = v->datamax;
00671   }
00672 
00673   if (volumeTexture.getTextureMap() && !(needRegenerate & COL_REGEN) &&
00674       volid == voltexVolid && atomColor->method() == voltexColorMethod &&
00675       voltexDataMin == vmin && voltexDataMax == vmax) {
00676     // nothing to do
00677     return;
00678   }
00679 
00680   voltexColorMethod = atomColor->method();
00681   voltexVolid = volid;
00682   voltexDataMin = vmin; 
00683   voltexDataMax = vmax;
00684 
00685   volumeTexture.setGridData(v);
00686 
00687   // update the volumeTexture instance
00688   switch (atomColor->method()) {
00689     case AtomColor::POS:
00690     case AtomColor::POSX:
00691     case AtomColor::POSY:
00692     case AtomColor::POSZ:
00693       volumeTexture.generatePosTexture();
00694       break;
00695 
00696     case AtomColor::INDEX:
00697       volumeTexture.generateIndexTexture();
00698       break;
00699 
00700     case AtomColor::CHARGE:
00701       volumeTexture.generateChargeTexture(vmin, vmax);
00702       break;
00703 
00704     case AtomColor::VOLUME:
00705       volumeTexture.generateColorScaleTexture(vmin, vmax, scene);
00706       break;
00707 
00708 #if 0
00709     case AtomColor::STRUCTURE:
00710       // 3-D Contour lines
00711       volumeTexture.generateContourLineTexture(0.5, 0.5);
00712       break;
00713 #endif
00714       
00715     case AtomColor::NAME:
00716     default:
00717       // HSV color ramp
00718       volumeTexture.generateHSVTexture(vmin, vmax);
00719       break;
00720   }
00721 }
00722 
00723 
00724 void DrawMolItem::draw_volslice(int volid, float slice, int axis, int texmode) {
00725   const VolumetricData *v = mol->get_volume_data(volid);
00726   float sliceNormal[3];
00727   float sliceTextureCoords[12];
00728   float sliceVertexes[12];
00729   if (!volumeTexture.getTextureMap()) {
00730     msgErr << "draw_volslice: no texture map has been generated!" << sendmsg;
00731     return;
00732   }
00733 
00734   sprintf(commentBuffer, "MoleculeID: %d ReprID: %d Beginning VolSlice",
00735           mol->id(), repNumber);
00736   cmdCommentX.putdata(commentBuffer, cmdList);
00737 
00738   prepare_texture_coordinates(v, slice, axis, sliceNormal, sliceTextureCoords,
00739                               sliceVertexes);
00740   
00741   // Rescale the texture coordinates so that they include just the 
00742   // part of the texture map to which we mapped our volume data.
00743   // Clamp range to just below 1.0 to prevent
00744   // textures from being clamped to the
00745   // border color on some video cards.
00746   float tscale[3] = { float(v->xsize), float(v->ysize), float(v->zsize) };
00747   const int *size = volumeTexture.getTextureSize();
00748   for (int i=0; i<3; i++) {
00749     float rescale = (tscale[i] / (float)size[i]) * 0.99999f;
00750     sliceTextureCoords[i  ] *= rescale;
00751     sliceTextureCoords[i+3] *= rescale;
00752     sliceTextureCoords[i+6] *= rescale;
00753     sliceTextureCoords[i+9] *= rescale;
00754   }
00755   // add command to draw the slice itself.
00756   append(DMATERIALON); // enable lighting and shading
00757 
00758   // Pass instructions for the slice itself.
00759   cmdVolSlice.putdata(texmode, sliceNormal, sliceVertexes, sliceTextureCoords, cmdList);
00760 }
00761 
00762 
00763 void DrawMolItem::draw_isosurface(int volid, float isovalue, int drawbox, int style, int stepsize, int thickness) {
00764   const VolumetricData * v = NULL;
00765 
00766   v = mol->get_volume_data(volid);
00767   if (v == NULL) {
00768     msgInfo << "No volume data loaded at index " << volid << sendmsg;
00769     return;
00770   } 
00771 
00772   sprintf(commentBuffer, "MoleculeID: %d ReprID: %d Beginning Isosurface",
00773           mol->id(), repNumber);
00774   cmdCommentX.putdata(commentBuffer, cmdList);
00775 
00776   // Safety checks to prevent stepsize from cratering surface extraction code
00777   if (stepsize >= v->xsize)
00778     stepsize = (v->xsize - 1);
00779   if (stepsize >= v->ysize)
00780     stepsize = (v->ysize - 1);
00781   if (stepsize >= v->zsize)
00782     stepsize = (v->zsize - 1);
00783   if (stepsize < 2)
00784     stepsize = 1;
00785 
00786   if (drawbox > 0) {
00787     // don't texture the box if color by volume is active
00788     if (atomColor->method() == AtomColor::VOLUME) {
00789       append(DVOLTEXOFF);
00790     }
00791     // wireframe only?  or solid?
00792     if (style > 0 || drawbox == 2) {
00793       draw_volume_box_lines(v);
00794     } else {
00795       draw_volume_box_solid(v);
00796     }
00797     if (atomColor->method() == AtomColor::VOLUME) {
00798       append(DVOLTEXON);
00799     }
00800   } 
00801 
00802   if ((drawbox == 2) || (drawbox == 0)) {
00803     switch (style) {
00804       case 3:
00805         // shaded points isosurface looping over X-axis, 1 point per voxel
00806         draw_volume_isosurface_lit_points(v, isovalue, stepsize, thickness);
00807         break;
00808 
00809       case 2:
00810         // points isosurface looping over X-axis, max of 1 point per voxel
00811         draw_volume_isosurface_points(v, isovalue, stepsize, thickness);
00812         break;
00813 
00814       case 1:
00815         // lines implementation, max of 18 line per voxel (3-per triangle)
00816         draw_volume_isosurface_lines(v, isovalue, stepsize, thickness);
00817         break;
00818 
00819       case 0:
00820       default:
00821         // trimesh polygonalized surface, max of 6 triangles per voxel
00822         draw_volume_isosurface_trimesh(v, isovalue, stepsize);
00823         break;
00824     }
00825   }
00826 }
00827 
00828 
00829 #if 0
00830 // draw a 2-D contour line in a slice plane
00831 void DrawMolItem::draw_volslice_contour_lines(int volid, float slice, int axis) {
00832   const VolumetricData * v = NULL;
00833 
00834   v = mol->get_volume_data(volid);
00835 
00836   if (v == NULL) {
00837     msgInfo << "No volume data loaded at index " << volid << sendmsg;
00838     return;
00839   }
00840 
00841   msgInfo << "Placeholder for contour slice not implemented yet..."
00842 }
00843 #endif
00844 
00845 
00846 // calculate seed voxels for field lines based on gradient magnitude
00847 int DrawMolItem::calcseeds_gradient_magnitude(const VolumetricData * v, ResizeArray<float> *seeds, float seedmin, float seedmax) {
00848   float seedmin2 = seedmin*seedmin;
00849   float seedmax2 = seedmax*seedmax;
00850 
00851   int i;
00852   float vorigin[3];
00853   for (i=0; i<3; i++) {
00854     vorigin[i] = float(v->origin[i]);
00855   }
00856 
00857   // calculate cell axes
00858   float xax[3], yax[3], zax[3];
00859   v->cell_axes(xax, yax, zax);
00860 
00861   int maxseedcount = 50000;
00862   int seedcount = maxseedcount+1; // force loop to run once
00863   int stepsize = 1;
00864 
00865   // iterate if we generate more seeds than we can really use
00866   while (seedcount > maxseedcount) {
00867     seedcount=0;
00868     seeds->clear();
00869 
00870     int x,y,z;
00871     float pos[3];
00872     for (z=0; z<v->zsize && seedcount < maxseedcount; z+=stepsize) {
00873       for (y=0; y<v->ysize; y+=stepsize) {
00874         for (x=0; x<v->xsize; x+=stepsize) {
00875           float grad[3];
00876           float gradmag2;
00877           vec_copy(grad, &v->gradient[(z*v->xsize*v->ysize + y*v->xsize + x) * 3]);
00878           gradmag2 = dot_prod(grad, grad);
00879 
00880           if ((gradmag2 <= seedmax2) &&
00881               (gradmag2 >= seedmin2)) {
00882             pos[0] = vorigin[0] + x * xax[0] + y * yax[0] + z * zax[0];
00883             pos[1] = vorigin[1] + x * xax[1] + y * yax[1] + z * zax[1];
00884             pos[2] = vorigin[2] + x * xax[2] + y * yax[2] + z * zax[2];
00885   
00886             seedcount++;
00887             seeds->append(pos[0]);
00888             seeds->append(pos[1]);
00889             seeds->append(pos[2]);
00890           }
00891         }
00892       }
00893     }
00894     stepsize++; // increase stepsize if we have to try again
00895   }
00896   
00897   return seedcount;
00898 }
00899 
00900 
00901 // draw a 3-D field lines that follow the volume gradient
00902 void DrawMolItem::draw_volume_field_lines(int volid, float seedval, float minlen, float maxlen, float thickness) {
00903   const VolumetricData * v = NULL;
00904   v = mol->get_volume_data(volid);
00905   int printdonemesg=0;
00906 
00907   if (v == NULL) {
00908     msgInfo << "No volume data loaded at index " << volid << sendmsg;
00909     return;
00910   }
00911 
00912   int seedcount = 0;
00913   int pointcount = 0;
00914   int totalpointcount = 0;
00915   int usecolor;
00916   ResizeArray<float> seeds;
00917  
00918   append(DMATERIALOFF);
00919   usecolor = draw_volume_get_colorid();
00920   cmdColorIndex.putdata(usecolor, cmdList);
00921 
00922   seedcount = calcseeds_gradient_magnitude(v, &seeds, seedval*0.5f, seedval*1.5f);
00923 
00924   // Integrate field lines starting with each of the seeds to simulate
00925   // particle advection.
00926   // Uses Euler's approximation for solving the initial value problem.
00927   // We could get a more accurate solution using a fourth order Runge-Kutta
00928   // method, but with more math per iteration.  We may want to implement 
00929   // the integrator as a user selected option.
00930 
00931   // The choice of integration step size is currently arbitrary,
00932   // but will become a user-defined parameter, since it affects speed
00933   // and accuracy.  A good default might be 0.25 times the smallest
00934   // grid cell spacing axis.
00935   float lx, ly, lz;
00936   v->cell_lengths(&lx, &ly, &lz);
00937   float mincelllen=lx;
00938   mincelllen = (mincelllen < ly) ? mincelllen : ly;
00939   mincelllen = (mincelllen < lz) ? mincelllen : lz;
00940   float delta=mincelllen * 0.25f; // delta per step (compensates gradient magnitude)
00941 
00942   // minimum gradient magnitude, before we consider that we've found
00943   // a critical point in the dataset.
00944   float mingmag =  0.0001f;
00945 
00946   // max gradient magnitude, before we consider it a source/sink
00947   float maxgmag = 5;
00948 
00949   ResizeArray<float> points;
00950 
00951   // For each seed point, integrate in both positive and
00952   // negative directions for a field line length up to
00953   // the maxlen criterion.
00954   wkfmsgtimer *msgt = wkf_msg_timer_create(1);
00955   int seed;
00956   for (seed=0; seed < seedcount; seed++) {
00957     // emit UI messages as integrator runs, for long calculations...
00958     if (!(seed & 7) && wkf_msg_timer_timeout(msgt)) {
00959       char tmpbuf[128];
00960       sprintf(tmpbuf, "%6.2f %% complete", (100.0f * seed) / (float) seedcount);
00961       msgInfo << "integrating " << seedcount << " field lines: " << tmpbuf << sendmsg;
00962       printdonemesg=1;
00963     }
00964  
00965     int direction;
00966     for (direction=-1; direction != 1; direction=1) {
00967       float pos[3], comsum[3];
00968       vec_copy(pos, &seeds[seed*3]); // integration starting point is the seed
00969 
00970       // init the arrays
00971       points.clear();
00972 
00973       // main integration loop
00974       pointcount=0;
00975       totalpointcount++;
00976       float len=0;
00977       int iterations=0;
00978       float dir = (float) direction;
00979 
00980       vec_zero(comsum); // clear center of mass accumulator
00981 
00982       while ((len<maxlen) && (totalpointcount < 100000000)) {
00983         float grad[3];
00984 
00985         // sample gradient at the current position
00986         v->voxel_gradient_interpolate_from_coord(pos, grad);
00987 
00988         // Early-exit if we run out of bounds (gradient returned will
00989         // be a vector of NANs), run into a critical point (zero gradient)
00990         // or a huge gradient at a source/sink point in the dataset.
00991         float gmag = norm(grad);
00992         if (gmag < mingmag || gmag > maxgmag)
00993           break;
00994 
00995         // Draw the current point only after the gradient value
00996         // has been checked, so we don't end up with out-of-bounds
00997         // vertices.
00998         // Only emit a fraction of integration points for display since
00999         // the integrator stepsize needs to be small for more numerical
01000         // accuracy, but the field lines themselves can be well 
01001         // represented with fewer sample points.
01002         if (!(iterations & 1)) {
01003           // Add a vertex for this field line
01004           points.append(pos[0]);
01005           points.append(pos[1]);
01006           points.append(pos[2]);
01007 
01008           vec_incr(comsum, pos);
01009  
01010           pointcount++;
01011           totalpointcount++;
01012         }
01013 
01014         // adjust integration stepsize so we never move more than 
01015         // the distance specified by delta at each step, to compensate
01016         // for varying gradient magnitude
01017         vec_scaled_add(pos, dir * delta / gmag, grad); // integrate position
01018         len += delta; // accumulate distance
01019 
01020         iterations++;
01021       }
01022 
01023       int drawfieldline = 1;
01024 
01025       // only draw the field line for this seed if we have enough points.
01026       // If we haven't reached the minimum field line length, we'll
01027       // drop the whole field line.
01028       if (pointcount < 2 || len < minlen)
01029         drawfieldline = 0;
01030 
01031       // only draw if bounding sphere diameter exceeds minlen
01032       if (drawfieldline) {       
01033         float com[3];
01034         vec_scale(com, 1.0f / (float) pointcount, comsum);
01035         float minlen2 = minlen*minlen;
01036 
01037         drawfieldline = 0;
01038         int p;
01039         for (p=0; p<pointcount; p++) {
01040           if ((2.0f * distance2(com, &points[p*3])) > minlen2) {
01041             drawfieldline = 1;
01042             break;
01043           }
01044         }
01045       }
01046 
01047       // only draw the field line if it met all selection criteria
01048       if (drawfieldline) {
01049         cmdLineType.putdata(SOLIDLINE, cmdList);
01050         cmdLineWidth.putdata((int) thickness, cmdList);
01051         cmdColorIndex.putdata(usecolor, cmdList);
01052         DispCmdPolyLineArray cmdPolyLineArray;
01053         cmdPolyLineArray.putdata(&points[0], pointcount, cmdList);
01054       } 
01055     }
01056   }
01057   wkf_msg_timer_destroy(msgt);
01058 
01059   if (printdonemesg) 
01060     msgInfo << "field line integration complete." << sendmsg;
01061 }
01062 
01063 

Generated on Mon Nov 23 01:32:27 2009 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002