Main Page   Namespace List   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-2011 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.149 $      $Date: 2011/11/03 18:01:43 $
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                                      const float *voltex) {
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 1
00452   if (s.numtriangles > 0) {
00453     append(DMATERIALON); // enable lighting and shading
00454     int usecolor = draw_volume_get_colorid();
00455     cmdColorIndex.putdata(usecolor, cmdList);
00456 
00457     if (voltex != NULL) {
00458       // assign per-vertex colors by a 3-D texture map
00459       s.set_color_voltex_rgb3fv(voltex); 
00460     } else {
00461       // use a single color for the entire mesh
00462       s.set_color_rgb3fv(scene->color_value(usecolor)); 
00463     }
00464 
00465     // Create a triangle mesh
00466     // XXX don't try to stripify it since this triggers a crash in ACTC for
00467     //     unknown reasons
00468     cmdTriMesh.putdata(&s.v[0], &s.n[0], &s.c[0], s.v.num() / 3,
00469                        &s.f[0], s.numtriangles, 0, cmdList);
00470   }
00471 #else
00472   if (s.numtriangles > 0) {
00473     append(DMATERIALON); // enable lighting and shading
00474     int usecolor = draw_volume_get_colorid();
00475     cmdColorIndex.putdata(usecolor, cmdList);
00476 
00477     // draw surface with per-vertex normals using a vertex array
00478     float *c = new float[s.numtriangles * 9];
00479     const float *fp = scene->color_value(usecolor);
00480     int i;
00481     for (i=0; i<s.numtriangles; i++) { 
00482       int ind = i * 9;
00483 
00484       c[ind    ] = fp[0]; // Red
00485       c[ind + 1] = fp[1]; // Green
00486       c[ind + 2] = fp[2]; // Blue
00487 
00488       ind+=3;
00489       c[ind    ] = fp[0]; // Red
00490       c[ind + 1] = fp[1]; // Green
00491       c[ind + 2] = fp[2]; // Blue
00492 
00493       ind+=3;
00494       c[ind    ] = fp[0]; // Red
00495       c[ind + 1] = fp[1]; // Green
00496       c[ind + 2] = fp[2]; // Blue
00497     }
00498 
00499     // Create a triangle mesh
00500     // XXX don't try to stripify it since this triggers a crash in ACTC for
00501     //     unknown reasons
00502     cmdTriMesh.putdata(&s.v[0], &s.n[0], c, s.v.num() / 3,
00503                        &s.f[0], s.numtriangles, 0, cmdList);
00504 
00505     delete [] c;
00506   }
00507 #endif
00508 }
00509 
00510 
00511 // recompute sliceTextureCoord, sliceVertexCoord, and sliceNormal
00512 // using the given volumetric data set, axis, and offset
00513 // sliceAxis and sliceOffset.  
00514 static void prepare_texture_coordinates(const VolumetricData *v, 
00515     float loc, int axis, float *sliceNormal, float *sliceTextureCoords,
00516     float *sliceVertexes) {
00517 
00518   float t0[3], t1[3], t2[3], t3[3];
00519   float v0[3], v1[3], v2[3], v3[3];
00520   float normal[3];
00521 
00522   float vorigin[3], vxaxis[3], vyaxis[3], vzaxis[3];
00523   int i;
00524   for (i=0; i<3; i++) {
00525     vorigin[i] = float(v->origin[i]);
00526     vxaxis[i] = float(v->xaxis[i]);
00527     vyaxis[i] = float(v->yaxis[i]);
00528     vzaxis[i] = float(v->zaxis[i]);
00529   }
00530 
00531 
00532   if (loc < 0.0f)
00533       loc = 0.0f;
00534 
00535   if (loc > 1.0f)
00536       loc = 1.0f;
00537 
00538   switch (axis) {
00539     // X-Axis
00540     case 0:
00541     default:
00542       t0[0] = loc;
00543       t0[1] = 0.0f;
00544       t0[2] = 0.0f;
00545 
00546       t1[0] = loc;
00547       t1[1] = 0.0f;
00548       t1[2] = 1.0f;
00549 
00550       t2[0] = loc;
00551       t2[1] = 1.0f;
00552       t2[2] = 1.0f;
00553 
00554       t3[0] = loc;
00555       t3[1] = 1.0f;
00556       t3[2] = 0.0f;
00557 
00558       v0[0] = vorigin[0] + (vxaxis[0] * loc);
00559       v0[1] = vorigin[1] + (vxaxis[1] * loc);
00560       v0[2] = vorigin[2] + (vxaxis[2] * loc);
00561 
00562       v1[0] = v0[0] + vzaxis[0];
00563       v1[1] = v0[1] + vzaxis[1];
00564       v1[2] = v0[2] + vzaxis[2];
00565 
00566       v2[0] = v0[0] + vzaxis[0] + vyaxis[0];
00567       v2[1] = v0[1] + vzaxis[1] + vyaxis[1];
00568       v2[2] = v0[2] + vzaxis[2] + vyaxis[2];
00569 
00570       v3[0] = v0[0]             + vyaxis[0];
00571       v3[1] = v0[1]             + vyaxis[1];
00572       v3[2] = v0[2]             + vyaxis[2];
00573 
00574       normal[0] = vxaxis[0];
00575       normal[1] = vxaxis[1];
00576       normal[2] = vxaxis[2];
00577       vec_normalize(&normal[0]);
00578       break;
00579 
00580     // Y-Axis
00581     case 1:
00582       t0[0] = 0.0f;
00583       t0[1] = loc;
00584       t0[2] = 0.0f;
00585 
00586       t1[0] = 1.0f;
00587       t1[1] = loc;
00588       t1[2] = 0.0f;
00589 
00590       t2[0] = 1.0f;
00591       t2[1] = loc;
00592       t2[2] = 1.0f;
00593 
00594       t3[0] = 0.0f;
00595       t3[1] = loc;
00596       t3[2] = 1.0f;
00597 
00598       v0[0] = vorigin[0] + (vyaxis[0] * loc);
00599       v0[1] = vorigin[1] + (vyaxis[1] * loc);
00600       v0[2] = vorigin[2] + (vyaxis[2] * loc);
00601 
00602       v1[0] = v0[0] + vxaxis[0];
00603       v1[1] = v0[1] + vxaxis[1];
00604       v1[2] = v0[2] + vxaxis[2];
00605 
00606       v2[0] = v0[0] + vxaxis[0] + vzaxis[0];
00607       v2[1] = v0[1] + vxaxis[1] + vzaxis[1];
00608       v2[2] = v0[2] + vxaxis[2] + vzaxis[2];
00609 
00610       v3[0] = v0[0]             + vzaxis[0];
00611       v3[1] = v0[1]             + vzaxis[1];
00612       v3[2] = v0[2]             + vzaxis[2];
00613 
00614       normal[0] = vyaxis[0];
00615       normal[1] = vyaxis[1];
00616       normal[2] = vyaxis[2];
00617       vec_normalize(&normal[0]);
00618       break;
00619 
00620     // Z-Axis
00621     case 2:
00622       t0[0] = 0.0f;
00623       t0[1] = 0.0f;
00624       t0[2] = loc;
00625 
00626       t1[0] = 1.0f;
00627       t1[1] = 0.0f;
00628       t1[2] = loc;
00629 
00630       t2[0] = 1.0f;
00631       t2[1] = 1.0f;
00632       t2[2] = loc;
00633 
00634       t3[0] = 0.0f;
00635       t3[1] = 1.0f;
00636       t3[2] = loc;
00637 
00638       v0[0] = vorigin[0] + (vzaxis[0] * loc);
00639       v0[1] = vorigin[1] + (vzaxis[1] * loc);
00640       v0[2] = vorigin[2] + (vzaxis[2] * loc);
00641 
00642       v1[0] = v0[0] + vxaxis[0];
00643       v1[1] = v0[1] + vxaxis[1];
00644       v1[2] = v0[2] + vxaxis[2];
00645 
00646       v2[0] = v0[0] + vxaxis[0] + vyaxis[0];
00647       v2[1] = v0[1] + vxaxis[1] + vyaxis[1];
00648       v2[2] = v0[2] + vxaxis[2] + vyaxis[2];
00649 
00650       v3[0] = v0[0]             + vyaxis[0];
00651       v3[1] = v0[1]             + vyaxis[1];
00652       v3[2] = v0[2]             + vyaxis[2];
00653 
00654       normal[0] = vzaxis[0];
00655       normal[1] = vzaxis[1];
00656       normal[2] = vzaxis[2];
00657       vec_normalize(&normal[0]);
00658       break;
00659   }
00660 
00661   vec_copy(sliceTextureCoords  , t0);
00662   vec_copy(sliceTextureCoords+3, t1);
00663   vec_copy(sliceTextureCoords+6, t2);
00664   vec_copy(sliceTextureCoords+9, t3);
00665   vec_copy(sliceVertexes  , v0);
00666   vec_copy(sliceVertexes+3, v1);
00667   vec_copy(sliceVertexes+6, v2);
00668   vec_copy(sliceVertexes+9, v3);
00669   vec_copy(sliceNormal, normal);
00670 }
00671 
00672 void DrawMolItem::updateVolumeTexture() {
00673   float vmin, vmax;
00674   int volid = atomColor->volume_index();
00675   if (atomRep->method()==AtomRep::VOLSLICE) {
00676     // the volslice rep has its own volid specification
00677     volid = (int)atomRep->get_data(AtomRep::SPHERERES);
00678   }
00679 
00680   const VolumetricData *v = mol->get_volume_data(volid);
00681   if (v == NULL) {
00682     msgInfo << "No volume data loaded at index " << volid << sendmsg;
00683     return;
00684   } 
00685 
00686   // determine if a new 3D texture needs to be prepared and uploaded.  This
00687   // occurs if:
00688   // (1) the coloring method has changed
00689   // (2) the choice of volumetric data set has changed.
00690   atomColor->get_colorscale_minmax(&vmin, &vmax);
00691   if (!vmin && !vmax) {
00692     vmin = v->datamin;
00693     vmax = v->datamax;
00694   }
00695 
00696   if (volumeTexture.getTextureMap() && !(needRegenerate & COL_REGEN) &&
00697       volid == voltexVolid && atomColor->method() == voltexColorMethod &&
00698       voltexDataMin == vmin && voltexDataMax == vmax) {
00699     // nothing to do
00700     return;
00701   }
00702 
00703   voltexColorMethod = atomColor->method();
00704   voltexVolid = volid;
00705   voltexDataMin = vmin; 
00706   voltexDataMax = vmax;
00707 
00708   volumeTexture.setGridData(v);
00709 
00710   // update the volumeTexture instance
00711   switch (atomColor->method()) {
00712     case AtomColor::POS:
00713     case AtomColor::POSX:
00714     case AtomColor::POSY:
00715     case AtomColor::POSZ:
00716       volumeTexture.generatePosTexture();
00717       break;
00718 
00719     case AtomColor::INDEX:
00720       volumeTexture.generateIndexTexture();
00721       break;
00722 
00723     case AtomColor::CHARGE:
00724       volumeTexture.generateChargeTexture(vmin, vmax);
00725       break;
00726 
00727     case AtomColor::VOLUME:
00728       volumeTexture.generateColorScaleTexture(vmin, vmax, scene);
00729       break;
00730 
00731 #if 0
00732     case AtomColor::STRUCTURE:
00733       // 3-D Contour lines
00734       volumeTexture.generateContourLineTexture(0.5, 0.5);
00735       break;
00736 #endif
00737       
00738     case AtomColor::NAME:
00739     default:
00740       // HSV color ramp
00741       volumeTexture.generateHSVTexture(vmin, vmax);
00742       break;
00743   }
00744 }
00745 
00746 
00747 void DrawMolItem::draw_volslice(int volid, float slice, int axis, int texmode) {
00748   const VolumetricData *v = mol->get_volume_data(volid);
00749   float sliceNormal[3];
00750   float sliceTextureCoords[12];
00751   float sliceVertexes[12];
00752   if (!volumeTexture.getTextureMap()) {
00753     msgErr << "draw_volslice: no texture map has been generated!" << sendmsg;
00754     return;
00755   }
00756 
00757   sprintf(commentBuffer, "MoleculeID: %d ReprID: %d Beginning VolSlice",
00758           mol->id(), repNumber);
00759   cmdCommentX.putdata(commentBuffer, cmdList);
00760 
00761   prepare_texture_coordinates(v, slice, axis, sliceNormal, sliceTextureCoords,
00762                               sliceVertexes);
00763   
00764   // Rescale the texture coordinates so that they include just the 
00765   // part of the texture map to which we mapped our volume data.
00766   // Clamp range to just below 1.0 to prevent
00767   // textures from being clamped to the
00768   // border color on some video cards.
00769   float tscale[3] = { float(v->xsize), float(v->ysize), float(v->zsize) };
00770   const int *size = volumeTexture.getTextureSize();
00771   for (int i=0; i<3; i++) {
00772     float rescale = (tscale[i] / (float)size[i]) * 0.99999f;
00773     sliceTextureCoords[i  ] *= rescale;
00774     sliceTextureCoords[i+3] *= rescale;
00775     sliceTextureCoords[i+6] *= rescale;
00776     sliceTextureCoords[i+9] *= rescale;
00777   }
00778   // add command to draw the slice itself.
00779   append(DMATERIALON); // enable lighting and shading
00780 
00781   // Pass instructions for the slice itself.
00782   cmdVolSlice.putdata(texmode, sliceNormal, sliceVertexes, sliceTextureCoords, cmdList);
00783 }
00784 
00785 
00786 void DrawMolItem::draw_isosurface(int volid, float isovalue, int drawbox, int style, int stepsize, int thickness) {
00787   const VolumetricData * v = NULL;
00788 
00789   v = mol->get_volume_data(volid);
00790   if (v == NULL) {
00791     msgInfo << "No volume data loaded at index " << volid << sendmsg;
00792     return;
00793   } 
00794 
00795   sprintf(commentBuffer, "MoleculeID: %d ReprID: %d Beginning Isosurface",
00796           mol->id(), repNumber);
00797   cmdCommentX.putdata(commentBuffer, cmdList);
00798 
00799   // Safety checks to prevent stepsize from cratering surface extraction code
00800   if (stepsize >= v->xsize)
00801     stepsize = (v->xsize - 1);
00802   if (stepsize >= v->ysize)
00803     stepsize = (v->ysize - 1);
00804   if (stepsize >= v->zsize)
00805     stepsize = (v->zsize - 1);
00806   if (stepsize < 2)
00807     stepsize = 1;
00808 
00809   if (drawbox > 0) {
00810     // don't texture the box if color by volume is active
00811     if (atomColor->method() == AtomColor::VOLUME) {
00812       append(DVOLTEXOFF);
00813     }
00814     // wireframe only?  or solid?
00815     if (style > 0 || drawbox == 2) {
00816       draw_volume_box_lines(v);
00817     } else {
00818       draw_volume_box_solid(v);
00819     }
00820     if (atomColor->method() == AtomColor::VOLUME) {
00821       append(DVOLTEXON);
00822     }
00823   } 
00824 
00825   if ((drawbox == 2) || (drawbox == 0)) {
00826     switch (style) {
00827       case 3:
00828         // shaded points isosurface looping over X-axis, 1 point per voxel
00829         draw_volume_isosurface_lit_points(v, isovalue, stepsize, thickness);
00830         break;
00831 
00832       case 2:
00833         // points isosurface looping over X-axis, max of 1 point per voxel
00834         draw_volume_isosurface_points(v, isovalue, stepsize, thickness);
00835         break;
00836 
00837       case 1:
00838         // lines implementation, max of 18 line per voxel (3-per triangle)
00839         draw_volume_isosurface_lines(v, isovalue, stepsize, thickness);
00840         break;
00841 
00842       case 0:
00843       default:
00844         // trimesh polygonalized surface, max of 6 triangles per voxel
00845         draw_volume_isosurface_trimesh(v, isovalue, stepsize);
00846         break;
00847     }
00848   }
00849 }
00850 
00851 
00852 #if 0
00853 // draw a 2-D contour line in a slice plane
00854 void DrawMolItem::draw_volslice_contour_lines(int volid, float slice, int axis) {
00855   const VolumetricData * v = NULL;
00856 
00857   v = mol->get_volume_data(volid);
00858 
00859   if (v == NULL) {
00860     msgInfo << "No volume data loaded at index " << volid << sendmsg;
00861     return;
00862   }
00863 
00864   msgInfo << "Placeholder for contour slice not implemented yet..."
00865 }
00866 #endif
00867 
00868 
00869 // calculate seed voxels for field lines based on gradient magnitude
00870 int DrawMolItem::calcseeds_gradient_magnitude(const VolumetricData * v, ResizeArray<float> *seeds, float seedmin, float seedmax) {
00871   float seedmin2 = seedmin*seedmin;
00872   float seedmax2 = seedmax*seedmax;
00873 
00874   int i;
00875   float vorigin[3];
00876   for (i=0; i<3; i++) {
00877     vorigin[i] = float(v->origin[i]);
00878   }
00879 
00880   // calculate cell axes
00881   float xax[3], yax[3], zax[3];
00882   v->cell_axes(xax, yax, zax);
00883 
00884   int maxseedcount = 50000;
00885   int seedcount = maxseedcount+1; // force loop to run once
00886   int stepsize = 1;
00887 
00888   // iterate if we generate more seeds than we can really use
00889   while (seedcount > maxseedcount) {
00890     seedcount=0;
00891     seeds->clear();
00892 
00893     int x,y,z;
00894     float pos[3];
00895     for (z=0; z<v->zsize && seedcount < maxseedcount; z+=stepsize) {
00896       for (y=0; y<v->ysize; y+=stepsize) {
00897         for (x=0; x<v->xsize; x+=stepsize) {
00898           float grad[3];
00899           float gradmag2;
00900           vec_copy(grad, &v->gradient[(z*v->xsize*v->ysize + y*v->xsize + x) * 3]);
00901           gradmag2 = dot_prod(grad, grad);
00902 
00903           if ((gradmag2 <= seedmax2) &&
00904               (gradmag2 >= seedmin2)) {
00905             pos[0] = vorigin[0] + x * xax[0] + y * yax[0] + z * zax[0];
00906             pos[1] = vorigin[1] + x * xax[1] + y * yax[1] + z * zax[1];
00907             pos[2] = vorigin[2] + x * xax[2] + y * yax[2] + z * zax[2];
00908   
00909             seedcount++;
00910             seeds->append(pos[0]);
00911             seeds->append(pos[1]);
00912             seeds->append(pos[2]);
00913           }
00914         }
00915       }
00916     }
00917     stepsize++; // increase stepsize if we have to try again
00918   }
00919   
00920   return seedcount;
00921 }
00922 
00923 
00924 // draw a 3-D field lines that follow the volume gradient
00925 void DrawMolItem::draw_volume_field_lines(int volid, float seedval, float minlen, float maxlen, float thickness) {
00926   const VolumetricData * v = NULL;
00927   v = mol->get_volume_data(volid);
00928   int printdonemesg=0;
00929 
00930   if (v == NULL) {
00931     msgInfo << "No volume data loaded at index " << volid << sendmsg;
00932     return;
00933   }
00934 
00935   int seedcount = 0;
00936   int pointcount = 0;
00937   int totalpointcount = 0;
00938   int usecolor;
00939   ResizeArray<float> seeds;
00940  
00941   append(DMATERIALOFF);
00942   usecolor = draw_volume_get_colorid();
00943   cmdColorIndex.putdata(usecolor, cmdList);
00944 
00945   seedcount = calcseeds_gradient_magnitude(v, &seeds, seedval*0.5f, seedval*1.5f);
00946 
00947   // Integrate field lines starting with each of the seeds to simulate
00948   // particle advection.
00949   // Uses Euler's approximation for solving the initial value problem.
00950   // We could get a more accurate solution using a fourth order Runge-Kutta
00951   // method, but with more math per iteration.  We may want to implement 
00952   // the integrator as a user selected option.
00953 
00954   // The choice of integration step size is currently arbitrary,
00955   // but will become a user-defined parameter, since it affects speed
00956   // and accuracy.  A good default might be 0.25 times the smallest
00957   // grid cell spacing axis.
00958   float lx, ly, lz;
00959   v->cell_lengths(&lx, &ly, &lz);
00960   float mincelllen=lx;
00961   mincelllen = (mincelllen < ly) ? mincelllen : ly;
00962   mincelllen = (mincelllen < lz) ? mincelllen : lz;
00963   float delta=mincelllen * 0.25f; // delta per step (compensates gradient magnitude)
00964 
00965   // minimum gradient magnitude, before we consider that we've found
00966   // a critical point in the dataset.
00967   float mingmag =  0.0001f;
00968 
00969   // max gradient magnitude, before we consider it a source/sink
00970   float maxgmag = 5;
00971 
00972   ResizeArray<float> points;
00973 
00974   // For each seed point, integrate in both positive and
00975   // negative directions for a field line length up to
00976   // the maxlen criterion.
00977   wkfmsgtimer *msgt = wkf_msg_timer_create(1);
00978   int seed;
00979   for (seed=0; seed < seedcount; seed++) {
00980     // emit UI messages as integrator runs, for long calculations...
00981     if (!(seed & 7) && wkf_msg_timer_timeout(msgt)) {
00982       char tmpbuf[128];
00983       sprintf(tmpbuf, "%6.2f %% complete", (100.0f * seed) / (float) seedcount);
00984       msgInfo << "integrating " << seedcount << " field lines: " << tmpbuf << sendmsg;
00985       printdonemesg=1;
00986     }
00987  
00988     int direction;
00989     for (direction=-1; direction != 1; direction=1) {
00990       float pos[3], comsum[3];
00991       vec_copy(pos, &seeds[seed*3]); // integration starting point is the seed
00992 
00993       // init the arrays
00994       points.clear();
00995 
00996       // main integration loop
00997       pointcount=0;
00998       totalpointcount++;
00999       float len=0;
01000       int iterations=0;
01001       float dir = (float) direction;
01002 
01003       vec_zero(comsum); // clear center of mass accumulator
01004 
01005       while ((len<maxlen) && (totalpointcount < 100000000)) {
01006         float grad[3];
01007 
01008         // sample gradient at the current position
01009         v->voxel_gradient_interpolate_from_coord(pos, grad);
01010 
01011         // Early-exit if we run out of bounds (gradient returned will
01012         // be a vector of NANs), run into a critical point (zero gradient)
01013         // or a huge gradient at a source/sink point in the dataset.
01014         float gmag = norm(grad);
01015         if (gmag < mingmag || gmag > maxgmag)
01016           break;
01017 
01018         // Draw the current point only after the gradient value
01019         // has been checked, so we don't end up with out-of-bounds
01020         // vertices.
01021         // Only emit a fraction of integration points for display since
01022         // the integrator stepsize needs to be small for more numerical
01023         // accuracy, but the field lines themselves can be well 
01024         // represented with fewer sample points.
01025         if (!(iterations & 1)) {
01026           // Add a vertex for this field line
01027           points.append(pos[0]);
01028           points.append(pos[1]);
01029           points.append(pos[2]);
01030 
01031           vec_incr(comsum, pos);
01032  
01033           pointcount++;
01034           totalpointcount++;
01035         }
01036 
01037         // adjust integration stepsize so we never move more than 
01038         // the distance specified by delta at each step, to compensate
01039         // for varying gradient magnitude
01040         vec_scaled_add(pos, dir * delta / gmag, grad); // integrate position
01041         len += delta; // accumulate distance
01042 
01043         iterations++;
01044       }
01045 
01046       int drawfieldline = 1;
01047 
01048       // only draw the field line for this seed if we have enough points.
01049       // If we haven't reached the minimum field line length, we'll
01050       // drop the whole field line.
01051       if (pointcount < 2 || len < minlen)
01052         drawfieldline = 0;
01053 
01054       // only draw if bounding sphere diameter exceeds minlen
01055       if (drawfieldline) {       
01056         float com[3];
01057         vec_scale(com, 1.0f / (float) pointcount, comsum);
01058         float minlen2 = minlen*minlen;
01059 
01060         drawfieldline = 0;
01061         int p;
01062         for (p=0; p<pointcount; p++) {
01063           if ((2.0f * distance2(com, &points[p*3])) > minlen2) {
01064             drawfieldline = 1;
01065             break;
01066           }
01067         }
01068       }
01069 
01070       // only draw the field line if it met all selection criteria
01071       if (drawfieldline) {
01072         cmdLineType.putdata(SOLIDLINE, cmdList);
01073         cmdLineWidth.putdata((int) thickness, cmdList);
01074         cmdColorIndex.putdata(usecolor, cmdList);
01075         DispCmdPolyLineArray cmdPolyLineArray;
01076         cmdPolyLineArray.putdata(&points[0], pointcount, cmdList);
01077       } 
01078     }
01079   }
01080   wkf_msg_timer_destroy(msgt);
01081 
01082   if (printdonemesg) 
01083     msgInfo << "field line integration complete." << sendmsg;
01084 }
01085 
01086 

Generated on Tue May 21 01:46:12 2013 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002