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

Scene.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2019 The Board of Trustees of the           
00004  *cr                        University of Illinois                       
00005  *cr                         All Rights Reserved                        
00006  *cr                                                                   
00007  ***************************************************************************/
00008 /***************************************************************************
00009  * RCS INFORMATION:
00010  *
00011  *      $RCSfile: Scene.C,v $
00012  *      $Author: johns $        $Locker:  $             $State: Exp $
00013  *      $Revision: 1.100 $      $Date: 2021/12/21 22:56:37 $
00014  *
00015  ***************************************************************************/
00026 #include "Scene.h"
00027 #include "DisplayDevice.h"
00028 #include "Inform.h"
00029 #include "DispCmds.h"
00030 #include "utilities.h"
00031 #include "FileRenderList.h"
00032 #include "FileRenderer.h"
00033 #include "ColorScaleTables.h"
00034 
00035 static const int num_scalemethods = 36;
00036 static const ColorScale defScales[] = {
00037  { {1.0, 0.0, 0.0}, {1.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, "RWB"},
00038  { {0.0, 0.0, 1.0}, {1.0, 1.0, 1.0}, {1.0, 0.0, 0.0}, "BWR"},
00039  { {1.0, 0.0, 0.0}, {0.5, 0.5, 0.5}, {0.0, 0.0, 1.0}, "RGryB"},
00040  { {0.0, 0.0, 1.0}, {0.5, 0.5, 0.5}, {1.0, 0.0, 0.0}, "BGryR"},
00041  { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, "RGB"},
00042  { {0.0, 0.0, 1.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, "BGR"},
00043  { {1.0, 0.0, 0.0}, {1.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, "RWG"},
00044  { {0.0, 1.0, 0.0}, {1.0, 1.0, 1.0}, {1.0, 0.0, 0.0}, "GWR"},
00045  { {0.0, 1.0, 0.0}, {1.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, "GWB"},
00046  { {0.0, 0.0, 1.0}, {1.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, "BWG"},
00047  { {0.0, 0.0, 0.0}, {0.5, 0.5, 0.5}, {1.0, 1.0, 1.0}, "BlkW"},
00048  { {1.0, 1.0, 1.0}, {0.5, 0.5, 0.5}, {0.0, 0.0, 0.0}, "WBlk"},
00049 
00050  // sequential
00051  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "cividis"},
00052  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "viridis"},
00053  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "magma"},
00054  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "plasma"},
00055  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "inferno"},
00056 
00057  // sequential-linear
00058  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "CET_L3"},
00059  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "CET_L8"},
00060  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "CET_L9"}, 
00061  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "CET_L16"}, 
00062  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "CET_L17"}, 
00063  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "CET_L18"}, 
00064  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "CET_L19"}, 
00065  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "CET_L20"}, 
00066 
00067  // cyclic
00068  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "CET_C2"},
00069  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "CET_C4"},
00070  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "CET_C6"},
00071  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "CET_C7"},
00072 
00073  // isoluminant
00074  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "CET_I1"},
00075  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "CET_I2"},
00076  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "CET_I3"},
00077  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "CET_D11"},
00078  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "CET_D12"},
00079 
00080  // rainbow
00081  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "turbo"},
00082  { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, "CET_R2"} 
00083 };
00084 
00085 static const char *colScaleMenuNames[] = {
00086  "RWB",
00087  "BWR",
00088  "RGryB",
00089  "BGryR",
00090  "RGB",
00091  "BGR",
00092  "RWG",
00093  "GWR",
00094  "GWB",
00095  "BWG",
00096  "BlkW",
00097  "WBlk",
00098 
00099  "Sequential/cividis",
00100  "Sequential/viridis",
00101  "Sequential/magma",
00102  "Sequential/plasma",
00103  "Sequential/inferno",
00104 
00105  "Linear/CET_L3",
00106  "Linear/CET_L8",
00107  "Linear/CET_L9",
00108  "Linear/CET_L16",
00109  "Linear/CET_L17",
00110  "Linear/CET_L18",
00111  "Linear/CET_L19",
00112  "Linear/CET_L20",
00113 
00114  "Cyclic/CET_C2",
00115  "Cyclic/CET_C4",
00116  "Cyclic/CET_C6",
00117  "Cyclic/CET_C7",
00118 
00119  "Isoluminant/CET_I1",
00120  "Isoluminant/CET_I2",
00121  "Isoluminant/CET_I3",
00122  "Isoluminant/CET_D11",
00123  "Isoluminant/CET_D12",
00124 
00125  "Rainbow/Turbo",
00126  "Rainbow/CET_R2"
00127 };
00128 
00129 
00130 enum colorScaleType {
00131   SCALE_TYPE_TABULATED=0,
00132   SCALE_TYPE_TABULATED_SRGB=1,
00133   SCALE_TYPE_DIVERGENT=2
00134 };
00135 
00136 
00138 class ColorScaleTypeInfo {
00139 public:
00140   enum colorScaleType type;
00141   const float *colortable;
00142   int colortabsz;
00143 
00144 #if 0
00145   int operator==(const ColorScale c) {
00146     return !memcmp(&c, this, sizeof(ColorScale));
00147   }
00148 #endif
00149 };
00150 
00151 
00152 // hard-coded color scale types
00153 static const ColorScaleTypeInfo scaleTypes[] = {
00154   {SCALE_TYPE_DIVERGENT,            NULL,   0}, // "RWB"
00155   {SCALE_TYPE_DIVERGENT,            NULL,   0}, // "BWR"
00156   {SCALE_TYPE_DIVERGENT,            NULL,   0}, // "RGryB"
00157   {SCALE_TYPE_DIVERGENT,            NULL,   0}, // "BGryR"
00158   {SCALE_TYPE_DIVERGENT,            NULL,   0}, // "RGB"
00159   {SCALE_TYPE_DIVERGENT,            NULL,   0}, // "BGR"
00160   {SCALE_TYPE_DIVERGENT,            NULL,   0}, // "RWG"
00161   {SCALE_TYPE_DIVERGENT,            NULL,   0}, // "GWR"
00162   {SCALE_TYPE_DIVERGENT,            NULL,   0}, // "GWB"
00163   {SCALE_TYPE_DIVERGENT,            NULL,   0}, // "BWG"
00164   {SCALE_TYPE_DIVERGENT,            NULL,   0}, // "BlkW"
00165   {SCALE_TYPE_DIVERGENT,            NULL,   0}, // "WBlk"
00166 
00167   {SCALE_TYPE_TABULATED,    cividis_data, 255}, // "cividis"
00168   {SCALE_TYPE_TABULATED,    viridis_data, 255}, // "viridis"
00169   {SCALE_TYPE_TABULATED,      magma_data, 255}, // "plasma"
00170   {SCALE_TYPE_TABULATED,     plasma_data, 255}, // "inferno"
00171   {SCALE_TYPE_TABULATED,    inferno_data, 255}, // "magma"
00172 
00173   {SCALE_TYPE_TABULATED,     CET_L3_data, 255}, // linear
00174   {SCALE_TYPE_TABULATED,     CET_L8_data, 255}, // linear
00175   {SCALE_TYPE_TABULATED,     CET_L9_data, 255}, // linear
00176   {SCALE_TYPE_TABULATED,    CET_L16_data, 255}, // linear
00177   {SCALE_TYPE_TABULATED,    CET_L17_data, 255}, // linear
00178   {SCALE_TYPE_TABULATED,    CET_L18_data, 255}, // linear
00179   {SCALE_TYPE_TABULATED,    CET_L19_data, 255}, // linear
00180   {SCALE_TYPE_TABULATED,    CET_L20_data, 255}, // linear
00181 
00182   {SCALE_TYPE_TABULATED,     CET_C2_data, 255}, // cyclic
00183   {SCALE_TYPE_TABULATED,     CET_C4_data, 255}, // cyclic 
00184   {SCALE_TYPE_TABULATED,     CET_C6_data, 255}, // cyclic 
00185   {SCALE_TYPE_TABULATED,     CET_C7_data, 255}, // cyclic 
00186 
00187   {SCALE_TYPE_TABULATED,     CET_I1_data, 255}, // isoluminant
00188   {SCALE_TYPE_TABULATED,     CET_I2_data, 255}, // isoluminant
00189   {SCALE_TYPE_TABULATED,     CET_I3_data, 255}, // isoluminant
00190   {SCALE_TYPE_TABULATED,    CET_D11_data, 255}, // isoluminant
00191   {SCALE_TYPE_TABULATED,    CET_D12_data, 255}, // isoluminant
00192 
00193   {SCALE_TYPE_TABULATED, turbo_srgb_data, 255}, // rainbow
00194   {SCALE_TYPE_TABULATED,     CET_R2_data, 255}  // rainbow
00195 };
00196 
00197 
00198 // maybe VMD should be using a color wheel scheme
00199 // to make it easier to pick contrasting and complementary 
00200 // colors.
00201 static const char *defColorNames[REGCLRS] = {
00202   "blue",    "red",    "gray",    "orange",  
00203   "yellow",  "tan",    "silver",  "green",  
00204   "white",   "pink",   "cyan",   "purple",
00205   "lime",    "mauve",  "ochre",  "iceblue", 
00206 
00207   // XXX black is expected to be at the end of the list
00208   "black"
00209 
00210 #if (REGCLRS > 17)
00211  ,"yellow2",  "yellow3",   "green2",    "green3",
00212   "cyan2",    "cyan3",     "blue2",     "blue3",
00213   "violet",   "violet2",   "magenta",   "magenta2",  
00214   "red2",     "red3",      "orange2",   "orange3"
00215 #endif
00216 
00217 };
00218 
00219 const float Scene::defaultColor[] = {
00220    0.0f,   0.0f, 1.00f,  1.0f,  0.0f,  0.0f, // BLUE, RED
00221    0.35f, 0.35f, 0.35f,  1.0f,  0.5f,  0.0f, // GREY, ORANGE
00222    1.0f,   1.0f,  0.0f,  0.5f,  0.5f,  0.2f, // YELLOW, TAN
00223    0.6f,   0.6f,  0.6f,  0.0f,  1.0f,  0.0f, // SILVER, GREEN
00224    1.0f,   1.0f,  1.0f,  1.0f,  0.6f,  0.6f, // WHITE, PINK
00225    0.25f, 0.75f, 0.75f, 0.65f,  0.0f, 0.65f, // CYAN, PURPLE
00226    0.5f,   0.9f,  0.4f,  0.9f,  0.4f,  0.7f, // LIME, MAUVE
00227    0.5f,   0.3f,  0.0f,  0.5f,  0.5f, 0.75f, // OCHRE, ICEBLUE
00228 
00229    // XXX black is expected to be at the end of the list
00230    0.0f,   0.0f,  0.0f                       // BLACK
00231   
00232 #if (REGCLRS > 17)
00233   ,0.88f, 0.97f, 0.02f,  0.55f, 0.90f, 0.02f, // yellow
00234    0.00f, 0.90f, 0.04f,  0.00f, 0.90f, 0.50f, // green
00235    0.00f, 0.88f, 1.00f,  0.00f, 0.76f, 1.00f, // cyan
00236    0.02f, 0.38f, 0.67f,  0.01f, 0.04f, 0.93f, // blue
00237    0.27f, 0.00f, 0.98f,  0.45f, 0.00f, 0.90f, // violet
00238    0.90f, 0.00f, 0.90f,  1.00f, 0.00f, 0.66f, // magenta
00239    0.98f, 0.00f, 0.23f,  0.81f, 0.00f, 0.00f, // red
00240    0.89f, 0.35f, 0.00f,  0.96f, 0.72f, 0.00f  // orange
00241 #endif
00242 
00243 };
00244 
00245 
00247 class DisplayColor : public Displayable {
00248 private:
00249   int colorCat;
00250   int dcindex;
00251   int dccolor;
00252   int changed;
00253  
00254 protected:
00255   void do_color_changed(int cat) {
00256     if (cat == colorCat) {
00257       dccolor = scene->category_item_value(colorCat, dcindex);
00258       changed = 1;
00259     }
00260   } 
00261   void do_color_rgb_changed(int color) {
00262     if (color == dccolor) 
00263       changed = 1;
00264   }
00265    
00266 public:
00267   DisplayColor(Displayable *d, const char *coloritemname, int colorindex)
00268   : Displayable(d), changed(0) {
00269     // Query the index of the Display color category, or add it if necessary
00270     colorCat = scene->category_index("Display");
00271     if (colorCat == -1) {
00272       colorCat = scene->add_color_category("Display");
00273     } 
00274     dcindex = scene->add_color_item(colorCat, coloritemname, colorindex);
00275     do_color_changed(colorCat);
00276   }
00277   int color_changed() const { return changed; }
00278   void clear_changed() { changed = 0; }
00279   int color_id() const { return dccolor; }
00280 };
00281 
00282 
00284 Scene::Scene() : root(this) {
00285   set_background_mode(0);
00286   reset_lights();
00287 
00288   // initialize color names and values
00289   int i;
00290   for (i=BEGREGCLRS; i<REGCLRS; i++) {
00291     colorNames.add_name(defColorNames[i], i);
00292     set_color_value(i, defaultColor + 3L*i);
00293   }
00294 
00295   // initialize color scale parameter info
00296   for (i=0; i<num_scalemethods; i++) {
00297     colorScales.append(defScales[i]);
00298     colorScaleMenuNames.append(colScaleMenuNames[i]);
00299   }
00300 
00301   scaleActive = 0;
00302   scaleMin = 0.06f; // default color scale "offset" value
00303   scaleMid = 0.50f; // default color scale "midpoint" value
00304   scaleMax = 1.00f;
00305   scalePosterize = 0;
00306   scaleReverse = 0;
00307   create_colorscale();
00308 
00309   // background color 
00310   background = new DisplayColor(&root, "Background", REGBLACK);
00311   background_color_changed = 0;
00312   background_color_id = 0;
00313 
00314   // background gradient colors
00315   backgradtop = new DisplayColor(&root, "BackgroundTop", REGBLACK);
00316   backgradtop_color_changed = 0;
00317   backgradtop_color_id = 0;
00318   backgradbot = new DisplayColor(&root, "BackgroundBot", REGBLUE2);
00319   backgradbot_color_changed = 0;
00320   backgradbot_color_id = 0;
00321 
00322   // foreground color
00323   foreground = new DisplayColor(&root, "Foreground", REGWHITE);
00324   foreground_color_changed = 0;
00325   foreground_color_id = 0;
00326 }
00327 
00329 Scene::~Scene(void) {
00330   for (int i=0; i<categories.num(); i++) delete categories.data(i);
00331 }
00332 
00334 
00335 // Set background drawing mode 
00336 void Scene::set_background_mode(int mode) {
00337   backgroundmode = mode;
00338   backgroundmode_changed = 1;
00339 }
00340 
00341 // Query background drawing mode 
00342 int Scene::background_mode(void) {
00343   return backgroundmode;
00344 }
00345 
00346 
00347 //
00348 // routines to deal with light sources
00349 //
00350   
00351 // default light data
00352 static const float def_light_color[3] = { 1.0, 1.0, 1.0 };
00353 static const float def_light_pos[DISP_LIGHTS][3] = {
00354         { -0.1f, 0.1f,  1.0f }, {  1.0f,  2.0f, 0.5f },
00355         { -1.0f, 2.0f, -1.0f }, { -1.0f, -1.0f, 0.0f }
00356 };
00357 static const float def_adv_light_pos[DISP_LIGHTS][3] = {
00358         { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, 
00359         { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }
00360 };
00361 
00362 static const int def_light_on[DISP_LIGHTS] = { TRUE, TRUE, FALSE, FALSE };
00363 
00364 void Scene::define_light(int n, const float *color, const float *position) {
00365   if (n < 0 || n >= DISP_LIGHTS)
00366     return;
00367   
00368   for (int i=0; i < 3; i++) {
00369     lightState[n].color[i] = color[i];
00370     lightState[n].pos[i] = position[i];
00371   }
00372   light_changed = 1;
00373 }
00374 
00375 void Scene::activate_light(int n, int turnon) {
00376   if (n < 0 || n >= DISP_LIGHTS )
00377     return;
00378   lightState[n].on = turnon;
00379   light_changed = 1;
00380 }
00381 
00382 void Scene::rotate_light(int n, float theta, char axis) {
00383   if (n < 0 || n >= DISP_LIGHTS)
00384     return;
00385   Matrix4 mat;
00386   mat.rot(theta,axis);
00387   mat.multpoint3d(lightState[n].pos,lightState[n].pos);
00388   light_changed = 1;
00389 }
00390 
00391 void Scene::move_light(int n, const float *p) {
00392   if (n < 0 || n >= DISP_LIGHTS) return;
00393   for (int i=0; i<3; i++) lightState[n].pos[i] = p[i];
00394   light_changed = 1;
00395 }
00396 
00397 const float *Scene::light_pos(int n) const {
00398   if (n < 0 || n >= DISP_LIGHTS) return NULL;
00399   return lightState[n].pos;
00400 }
00401 
00402 const float *Scene::light_pos_default(int n) const {
00403   if (n < 0 || n >= DISP_LIGHTS) return NULL;
00404   return def_light_pos[n];
00405 }
00406 
00407 const float *Scene::light_color(int n) const {
00408   if (n < 0 || n >= DISP_LIGHTS) return NULL;
00409   return lightState[n].color;
00410 }
00411 
00412 const float *Scene::light_color_default(int n) const {
00413   if (n < 0 || n >= DISP_LIGHTS) return NULL;
00414   return def_light_color;
00415 }
00416 
00417 
00418 void Scene::define_adv_light(int n, const float *color, 
00419                              const float *position,
00420                              float constant, float linear, float quad,
00421                              float *spotdir, 
00422                              float fallstart, float fallend, int spoton) {
00423   if (n < 0 || n >= DISP_LIGHTS)
00424     return;
00425   
00426   for (int i=0; i < 3; i++) {
00427     advLightState[n].color[i] = color[i];
00428     advLightState[n].pos[i] = position[i];
00429     advLightState[n].spotdir[i] = spotdir[i];
00430   }
00431   advLightState[n].constfactor = constant;
00432   advLightState[n].linearfactor = linear;
00433   advLightState[n].quadfactor = quad;
00434   advLightState[n].fallstart = fallstart;
00435   advLightState[n].fallend = fallend;
00436   advLightState[n].spoton = spoton;
00437   adv_light_changed = 1;
00438 }
00439 
00440 void Scene::activate_adv_light(int n, int turnon) {
00441   if (n < 0 || n >= DISP_LIGHTS )
00442     return;
00443   advLightState[n].on = turnon;
00444   adv_light_changed = 1;
00445 }
00446 
00447 void Scene::move_adv_light(int n, const float *p) {
00448   if (n < 0 || n >= DISP_LIGHTS) return;
00449   for (int i=0; i<3; i++) 
00450     advLightState[n].pos[i] = p[i];
00451   adv_light_changed = 1;
00452 }
00453 
00454 const float *Scene::adv_light_pos(int n) const {
00455   if (n < 0 || n >= DISP_LIGHTS) return NULL;
00456   return advLightState[n].pos;
00457 }
00458 
00459 const float *Scene::adv_light_pos_default(int n) const {
00460   if (n < 0 || n >= DISP_LIGHTS) return NULL;
00461   return def_adv_light_pos[n];
00462 }
00463 
00464 const float *Scene::adv_light_color(int n) const {
00465   if (n < 0 || n >= DISP_LIGHTS) return NULL;
00466   return advLightState[n].color;
00467 }
00468 
00469 const float *Scene::adv_light_color_default(int n) const {
00470   if (n < 0 || n >= DISP_LIGHTS) return NULL;
00471   return def_light_color;
00472 }
00473 
00474 void Scene::adv_light_attenuation(int n, float constant, float linear,
00475                                   float quad) {
00476   if (n < 0 || n >= DISP_LIGHTS) return;
00477   advLightState[n].constfactor = constant;
00478   advLightState[n].linearfactor = linear;
00479   advLightState[n].quadfactor = quad;
00480 }
00481 
00482 void Scene::adv_light_get_attenuation(int n, float &constant, float &linear,
00483                                       float &quad) const {
00484   if (n < 0 || n >= DISP_LIGHTS) return;
00485   constant = advLightState[n].constfactor;
00486   linear   = advLightState[n].linearfactor;
00487   quad     = advLightState[n].quadfactor;
00488 }
00489 
00490 void Scene::adv_light_spotlight(int n, float *spotdir, float fallstart, 
00491                                 float fallend, int spoton) {
00492   if (n < 0 || n >= DISP_LIGHTS) return;
00493   advLightState[n].fallstart = fallstart;
00494   advLightState[n].fallend = fallend;
00495   advLightState[n].spoton = spoton;
00496   for (int i=0; i<3; i++) 
00497     advLightState[n].spotdir[i] = spotdir[i];
00498 }
00499 
00500 const float *Scene::adv_light_get_spotlight(int n, float &fallstart, 
00501                                             float &fallend, int &spoton) const {
00502   if (n < 0 || n >= DISP_LIGHTS) return NULL;
00503   fallstart = advLightState[n].fallstart;
00504   fallend   = advLightState[n].fallend;
00505   spoton    = advLightState[n].spoton;
00506   return advLightState[n].spotdir;
00507 }
00508 
00509 void Scene::reset_lights(void) {
00510   int i;
00511 
00512   // standard directional lights
00513   for (i=0; i<DISP_LIGHTS; i++) { 
00514     define_light(i, def_light_color, def_light_pos[i]);
00515     activate_light(i, def_light_on[i]);
00516   }
00517   light_changed = 1;
00518 
00519   // advanced lights
00520   for (i=0; i<DISP_LIGHTS; i++) { 
00521     float spotdir[] = { 0.0f, 0.0f, 1.0f };
00522     define_adv_light(i, def_light_color, def_light_pos[i],
00523                      1.0f, 0.0f, 0.0f,
00524                      spotdir, 0.3f, 0.7f, 0);
00525     activate_adv_light(i, 0);
00526   }
00527   adv_light_changed = 1;
00528 }
00529 
00530 
00531 // prepare all registered Displayables
00532 int Scene::prepare() {
00533   background_color_changed = background->color_changed();
00534   background_color_id = background->color_id();
00535   background->clear_changed();
00536 
00537   backgradtop_color_changed = backgradtop->color_changed();
00538   backgradtop_color_id = backgradtop->color_id();
00539   backgradtop->clear_changed();
00540 
00541   backgradbot_color_changed = backgradbot->color_changed();
00542   backgradbot_color_id = backgradbot->color_id();
00543   backgradbot->clear_changed();
00544 
00545   foreground_color_changed = foreground->color_changed();
00546   foreground_color_id = foreground->color_id();
00547   foreground->clear_changed();
00548 
00549   return root.draw_prepare() || backgroundmode_changed || light_changed || 
00550          background_color_changed || 
00551          backgradtop_color_changed || backgradbot_color_changed || 
00552          foreground_color_changed;
00553 }
00554 
00555 // draws the scene to the given DisplayDevice
00556 // this is the only Scene which tells the display to do graphics commands
00557 //
00558 // XXX implementation of multi-pass rendering, accumulation buffers,
00559 //     and better snapshot behavior will require modifications to this
00560 //     mechanism.  The current system is very simple minded, and doesn't
00561 //     allow for property-based sorting of geometry, occlusion culling 
00562 //     algorithms, etc.  This needs to be changed.
00563 //
00564 // XXX note, this method should really be a 'const' method since
00565 //     it is run concurrently by several processes that share memory, but
00566 //     we can't actually write it that way since the locking routines do
00567 //     indeed write to lock variables.  The code in draw() should be written
00568 //     as though it were a const method however, at least in terms of what
00569 //     state is changed in the Scene class or subclass.
00570 //
00571 void Scene::draw(DisplayDevice *display) {
00572   if (!display)
00573     return;
00574 
00575   if (!display->is_renderer_process()) // master process doesn't draw
00576     return;
00577 
00578   // check background rendering mode
00579   if (backgroundmode_changed) {
00580     display->set_background_mode(backgroundmode);
00581   }
00582 
00583   // XXX Make a Displayable for lights, as we do for background color, and
00584   //     have a DispCmd for turning lights on and off.
00585   if (light_changed) {
00586     // set up the lights
00587     for (int i=0; i<DISP_LIGHTS; i++) {
00588       display->do_define_light(i, lightState[i].color, lightState[i].pos);
00589       display->do_activate_light(i, lightState[i].on);
00590     }
00591   }
00592 
00593 #if 0
00594   // XXX advanced lights are not yet implemented by displays
00595   // XXX Make a Displayable for lights, as we do for background color, and
00596   //     have a DispCmd for turning lights on and off.
00597   if (adv_light_changed) {
00598     // set up the lights
00599     for (int i=0; i<DISP_LIGHTS; i++) {
00600       display->do_define_light(i, lightState[i].color, lightState[i].pos);
00601       display->do_activate_light(i, lightState[i].on);
00602     }
00603   }
00604 #endif
00605 
00606   // update colors
00607   display->use_colors(colorData);
00608 
00609   // set the background color if any color definitions changed, or if the
00610   // the color assigned to background changed.  
00611   // XXX Make a DispCmd for background color so that background color can
00612   //     be handled automatically by the renderers, rather than special-cased
00613   //     as we do here.  This should work because the background displayable is
00614   //     the first item traversed in the scene graph. 
00615   if (background_color_changed) {
00616     display->set_background(color_value(background_color_id));
00617   }
00618 
00619   // set the background gradient colors if any definitions changed, or if
00620   // the color assigned to the gradient changed.
00621   if (backgradtop_color_changed || backgradbot_color_changed) {
00622     display->set_backgradient(color_value(backgradtop->color_id()),
00623                               color_value(backgradbot->color_id()));
00624   }
00625 
00626   // clear the display and set the viewport correctly
00627   display->prepare3D(TRUE);
00628 
00629   // on some machines with broken stereo implementations, we have
00630   // to draw in stereo even when VMD is set for mono mode
00631   // XXX this is all very ugly, and while this trick works for drawing
00632   // in normal mode, it doesn't fix the other single-buffer "stereo"
00633   // modes, since they don't fall into this test case.  Scene doesn't have
00634   // intimate knowledge of the details of the display subclass's 
00635   // stereo mode implementations, so a future rewrite will probably have
00636   // to move all of this code into the DisplayDevice class, with Scene
00637   // simply passing in a bunch of parameters so the display subclass
00638   // can deal with these problems for itself.
00639   if (display->forced_stereo_draws() && !(display->stereo_mode())) {
00640     display->left();  // this will be done as normal() since stereo is off
00641                       // but we'll actually draw to GL_BACK_LEFT
00642     display->prepareOpaque();
00643     root.draw(display);
00644     if (display->prepareTrans()) {
00645       root.draw(display);
00646     }
00647 
00648     display->right(); // this will be done as normal() since stereo is off
00649                       // but we'll actually draw to GL_BACK_RIGHT
00650     display->prepareOpaque();
00651     root.draw(display);
00652     if (display->prepareTrans()) {
00653       root.draw(display);
00654     }
00655   } else {
00656     // draw left eye first, if stereo
00657     if (display->stereo_mode())
00658       display->left();
00659     else
00660       display->normal();
00661 
00662     // draw all the objects for normal, or left eye position
00663     display->prepareOpaque();
00664     root.draw(display);
00665 
00666     if (display->prepareTrans()) {
00667       root.draw(display);
00668     }
00669    
00670     // now draw right eye, if in stereo
00671     if (display->stereo_mode()) {
00672       display->right();
00673       display->prepareOpaque();
00674       root.draw(display);
00675 
00676       if (display->prepareTrans()) {
00677         root.draw(display);
00678       }
00679     } 
00680   }  
00681 
00682   display->render_done();
00683   
00684   // update the display
00685   display->update(TRUE);
00686 }
00687 
00688 // draw the scene to a file in a given format, trying to match the
00689 // view of the given DisplayDevice as closely as possible
00690 // returns TRUE if successful, FALSE if not
00691 int Scene::filedraw(FileRenderer *render, const char *filename, 
00692                     DisplayDevice *display) {
00693   int i;
00694 
00695   // Copy all relevant info from the current main DisplayDevice
00696   (*((DisplayDevice *)render)) = (*display);
00697 
00698   // set up the lights
00699   for (i=0; i<DISP_LIGHTS; i++) {
00700     if (lightState[i].on)
00701       render->do_define_light(i, lightState[i].color, lightState[i].pos);
00702     render->do_activate_light(i, lightState[i].on);
00703   }
00704 
00705   // set up the advanced lights
00706   for (i=0; i<DISP_LIGHTS; i++) {
00707     if (advLightState[i].on)
00708       render->do_define_adv_light(i, 
00709                                   advLightState[i].color,
00710                                   advLightState[i].pos,
00711                                   advLightState[i].constfactor,
00712                                   advLightState[i].linearfactor,
00713                                   advLightState[i].quadfactor,
00714                                   advLightState[i].spotdir,
00715                                   advLightState[i].fallstart,
00716                                   advLightState[i].fallend,
00717                                   advLightState[i].spoton);
00718     render->do_activate_adv_light(i, advLightState[i].on);
00719   }
00720 
00721   // set up the colors
00722   render->use_colors(colorData);
00723   render->set_background(color_value(background->color_id()));
00724   render->set_backgradient(color_value(backgradtop->color_id()),
00725                            color_value(backgradbot->color_id()));
00726 
00727   // returns FALSE if not able to open file
00728   if (!render->open_file(filename)) {
00729     return FALSE;
00730   }
00731   // writes the header
00732   render->prepare3D(TRUE);
00733 
00734   // draw the scene to the file
00735   root.draw(render);
00736 
00737   // write the trailer and close
00738   render->render_done();
00739   render->update(TRUE);
00740 
00741   // rendering was successful
00742   return TRUE;
00743 }
00744 
00745 // state updates have to be done outside of the draw routine to prevent
00746 // race conditions when multiple slave renderers execute the draw() code.
00747 void Scene::draw_finished() {
00748   // only master process changes state flags
00749   backgroundmode_changed=0; // reset background mode change flag
00750   light_changed = 0;        // reset light changing state cache
00751   adv_light_changed = 0;    // reset light changing state cache
00752 }
00753 
00754 // create the color scale based on current settings
00755     
00757 // definitions for scales with 3 colors
00758 // 1 at val = 0; 0 at mid and greater
00759 static float slope3_lower(float mid, float val) {
00760   if (val > mid) return 0.0f;
00761   if (mid == 0) return 1.0f;
00762   return (1.0f - val / mid);
00763 }
00764   
00765 // 1 at val = 1; 0 at mid and lesser
00766 static float slope3_upper(float mid, float val) {
00767   if (val < mid) return 0.0f;
00768   if (mid == 1) return 1.0f;
00769   return (1.0f - (1.0f - val) / (1.0f - mid));
00770 } 
00771     
00772 // 1 at val = mid; 0 at val = 0 an 1
00773 static float slope3_middle(float mid, float val) {
00774   if (val < mid) {
00775     return val / mid;
00776   }
00777   if (val > mid) { 
00778     return (1-val) / (1-mid);
00779   } 
00780   return 1.0;
00781 }
00782   
00783     
00784 // given RGB values at (0,mid,1), return the correct RGB triplet
00785 static void scale_color(const float *lowRGB, const float *midRGB, 
00786                         const float *highRGB,
00787                         float mid, float val, float scaleMin, float *rgb) {
00788   float w1 = slope3_lower(mid, val);
00789   float w2 = slope3_middle(mid, val);
00790   float w3 = slope3_upper(mid, val);
00791   float wsum = (w1 + w2 + w3);
00792 
00793   rgb[0] = (lowRGB[0]*w1 + midRGB[0]*w2 + highRGB[0]*w3) / wsum + scaleMin;
00794   rgb[1] = (lowRGB[1]*w1 + midRGB[1]*w2 + highRGB[1]*w3) / wsum + scaleMin;
00795   rgb[2] = (lowRGB[2]*w1 + midRGB[2]*w2 + highRGB[2]*w3) / wsum + scaleMin;
00796 
00797   clamp_color(rgb);
00798 }
00799 
00800 void Scene::create_colorscale() {
00801   const ColorScale &scale = colorScales[scaleActive];
00802 
00803   if (scalePosterize <= 1) 
00804     scalePosterize = 0;
00805 
00806   int maxidx = MAPCLRS - 1;
00807   float fmaxidx_inv = 1.0f / float(maxidx);
00808   float fpost_inv = 1.0f / float(scalePosterize - 1);
00809 
00810   int i;
00811   switch (scaleTypes[scaleActive].type) {
00812     case SCALE_TYPE_DIVERGENT:
00813       for (i=0; i<=maxidx; i++) {
00814         int idx = (scaleReverse) ? (maxidx-i) : i;
00815         float *rcol = colorData + 3L*(BEGMAP + idx);
00816         float relpos = float(i) * fmaxidx_inv;
00817 
00818         relpos = (scalePosterize) ? (int(relpos * scalePosterize) * fpost_inv) : relpos;
00819 
00820         scale_color(scale.min, scale.mid, scale.max, 
00821                     scaleMid, relpos, scaleMin, rcol);
00822       }
00823       break;
00824 
00825     case SCALE_TYPE_TABULATED:
00826     case SCALE_TYPE_TABULATED_SRGB:
00827       const float *ctab = scaleTypes[scaleActive].colortable;
00828       if (ctab == NULL) {
00829         printf("color tab NULL!\n");
00830       }
00831 
00832       for (i=0; i<=maxidx; i++) {
00833         int idx = (scaleReverse) ? (maxidx-i) : i;
00834         float *rcol = colorData + 3L*(BEGMAP + idx);
00835         float relpos = float(i) / float(MAPCLRS-1);
00836 
00837         relpos = (scalePosterize) ? (int(relpos * scalePosterize) * fpost_inv) : relpos;
00838 
00839         int tabidx = int(scaleTypes[scaleActive].colortabsz * relpos);
00840         if (tabidx > scaleTypes[scaleActive].colortabsz)
00841           tabidx = scaleTypes[scaleActive].colortabsz;
00842 
00843         rcol[0] = ctab[3*tabidx    ];
00844         rcol[1] = ctab[3*tabidx + 1];
00845         rcol[2] = ctab[3*tabidx + 2];
00846       }
00847 
00848       // on-the-fly conversion of tabulated color scales from 
00849       // sRGB gamma color space to linear gamma RGB color space,
00850       if (scaleTypes[scaleActive].type == SCALE_TYPE_TABULATED_SRGB) {
00851         for (i=0; i<=maxidx; i++) {
00852           float *rcol = colorData + 3L*(BEGMAP + i);
00853           rcol[0] = powf(rcol[0], 2.2f);
00854           rcol[1] = powf(rcol[1], 2.2f);
00855           rcol[2] = powf(rcol[2], 2.2f);
00856         }
00857       }
00858       break;
00859   }
00860     
00861   root.color_scale_changed();
00862 }
00863 
00864 
00865 int Scene::colorscale_type(int index) {
00866   if (index < 0 || index >= num_scalemethods)
00867     return 0;
00868   return (scaleTypes[scaleActive].type != SCALE_TYPE_TABULATED);
00869 }
00870 
00871 
00872 int Scene::nearest_index(float r, float g, float b) const {
00873    const float *rcol = color_value(BEGREGCLRS);  // get the solid colors
00874    float lsq = r - rcol[0]; lsq *= lsq;
00875    float tmp = g - rcol[1]; lsq += tmp * tmp;
00876          tmp = b - rcol[2]; lsq += tmp * tmp;
00877    float best = lsq;
00878    int bestidx = BEGREGCLRS;
00879    for (int n= BEGREGCLRS+1; n < (BEGREGCLRS + REGCLRS); n++) {
00880       rcol = color_value(n); 
00881       lsq = r - rcol[0]; lsq *= lsq;
00882       tmp = g - rcol[1]; lsq += tmp * tmp;
00883       tmp = b - rcol[2]; lsq += tmp * tmp;
00884       if (lsq < best) {
00885        best = lsq;
00886        bestidx = n;
00887       }
00888    }
00889    return bestidx;
00890 }
00891 
00892 int Scene::get_colorscale_colors(int whichScale, 
00893       float min[3], float mid[3], float max[3]) {
00894   if (whichScale < 0 || whichScale >= colorScales.num())
00895     return FALSE;
00896   const ColorScale &scale = colorScales[whichScale];
00897   for (int i=0; i<3; i++) {
00898     min[i] = scale.min[i];
00899     mid[i] = scale.mid[i];
00900     max[i] = scale.max[i];
00901   }
00902   return TRUE;
00903 }
00904 
00905 int Scene::set_colorscale_colors(int whichScale, 
00906       const float min[3], const float mid[3], const float max[3]) {
00907   if (whichScale < 0 || whichScale >= colorScales.num())
00908     return FALSE;
00909   ColorScale &scale = colorScales[whichScale];
00910   for (int i=0; i<3; i++) {
00911     scale.min[i] = min[i];
00912     scale.mid[i] = mid[i];
00913     scale.max[i] = max[i];
00914   }
00915   create_colorscale();
00916   return TRUE;
00917 }
00918 

Generated on Thu Apr 25 02:43:34 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002