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

MaterialList.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: MaterialList.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.33 $      $Date: 2010/12/16 04:08:22 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *   Material properties list structure, master list of all materials
00019  ***************************************************************************/
00020 
00021 #include "MaterialList.h"
00022 #include "Displayable.h"
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <math.h>
00026 
00027 static const Material defOpaque = {
00028   0.00f, // ambient
00029   0.50f, // specular
00030   0.65f, // diffuse
00031  40.00f, // shininess 
00032   1.00f, // opacity
00033   0.00f, // outline
00034   0.00f, // outlinewidth
00035   0.00f, // transmode
00036   0      // index
00037 };
00038 
00039 static const Material defTransp = {
00040   0.00f, // ambient
00041   0.50f, // specular
00042   0.65f, // diffuse
00043  40.00f, // shininess 
00044   0.30f, // opacity
00045   0.00f, // outline
00046   0.00f, // outlinewidth
00047   0.00f, // transmode
00048   1      // index
00049 };
00050 
00051 
00052 // raw shininess values will run from 1 to 1000, but be scaled from 0 to 1
00053 // in the user interface.  If y is the internal value and x is the 
00054 // external (user interface value), then y = A exp(k * (x-0.5)), where...
00055 static const double SHINY_A = sqrt(1000.0);  // ...and...
00056 static const double SHINY_k = log(1000.0);
00057 
00058 MaterialList::MaterialList(Displayable *rootd) : root(rootd) {
00059   mlist = new NameList<Material *>;
00060   Material *opaque, *transp;
00061   opaque = new Material;
00062   transp = new Material;
00063   memcpy(opaque, &defOpaque, sizeof(Material));
00064   memcpy(transp, &defTransp, sizeof(Material));
00065   
00066   // add to list 
00067   mlist->add_name("Opaque",opaque);
00068   mlist->add_name("Transparent",transp);
00069 
00070   // the update_material makes all child displayables update as well; this
00071   // is needed in the case of Scene::root to make sure that Scene::background
00072   // is properly initialized.
00073   root->update_material(material(0));
00074   matcounter = 2;
00075 }
00076 
00077 void MaterialList::notify(int ind) {
00078   const Material *mat = mlist->data(ind);
00079   root->update_material(mat);
00080 }
00081 
00082 MaterialList::~MaterialList() {
00083   for (int i=0; i<mlist->num(); i++) delete mlist->data(i);
00084   delete mlist;
00085 }
00086 
00087 void MaterialList::set_name(int i, const char *nm) {
00088   mlist->set_name(i, nm);
00089 }
00090 
00091 void MaterialList::set_ambient(int i, float f) {
00092   if (i<0 || i >= num()) return;
00093   mlist->data(i)->ambient = f;
00094   notify(i);
00095 }
00096  
00097 void MaterialList::set_specular(int i, float f) {
00098   if (i<0 || i >= num()) return;
00099   mlist->data(i)->specular = f;
00100   notify(i);
00101 }
00102  
00103 void MaterialList::set_diffuse(int i, float f) {
00104   if (i<0 || i >= num()) return;
00105   mlist->data(i)->diffuse = f;
00106   notify(i);
00107 }
00108  
00109 void MaterialList::set_shininess(int i, float f) {
00110   if (i<0 || i >= num()) return;
00111   double val = SHINY_A * exp(SHINY_k * (f-0.5));
00112   mlist->data(i)->shininess = (float) val;
00113   notify(i);
00114 }
00115  
00116 void MaterialList::set_opacity(int i, float f) {
00117   if (i<0 || i >= num()) return;
00118   mlist->data(i)->opacity = f;
00119   notify(i);
00120 }
00121 
00122 void MaterialList::set_outline(int i, float f) {
00123   if (i<0 || i >= num()) return;
00124   mlist->data(i)->outline = f;
00125   notify(i);
00126 }
00127 
00128 void MaterialList::set_outlinewidth(int i, float f) {
00129   if (i<0 || i >= num()) return;
00130   mlist->data(i)->outlinewidth = f;
00131   notify(i);
00132 }
00133 
00134 void MaterialList::set_transmode(int i, float f) {
00135   if (i<0 || i >= num()) return;
00136   mlist->data(i)->transmode = f;
00137   notify(i);
00138 }
00139  
00140 const char *MaterialList::add_material(const char *newname, 
00141                                        const char *copyfrom) {
00142   int copyind = 0;
00143   if (copyfrom) {
00144     copyind = material_index(copyfrom);
00145     if (copyind < 0) return NULL;  // material to copy from does not exist
00146   }
00147   char buf[20];
00148   const char *name = newname;
00149   if (!name) {
00150     // find a new unique name.
00151     int id = mlist->num();
00152     do {
00153       sprintf(buf, "Material%d", id++);
00154       name = buf;
00155     } while (mlist->typecode(name) >= 0);
00156   } else {
00157     if (mlist->typecode(name) >= 0)
00158       return NULL; // name already present
00159   }
00160   Material *newmat = new Material;
00161   memcpy(newmat, mlist->data(copyind), sizeof(Material));
00162   newmat->ind = matcounter++;
00163   int ind = mlist->add_name(name, newmat);
00164   return mlist->name(ind);
00165 } 
00166 
00167 float MaterialList::get_ambient(int i) {
00168   return mlist->data(i)->ambient;
00169 }
00170 
00171 float MaterialList::get_specular(int i) {
00172   return mlist->data(i)->specular;
00173 }
00174 
00175 float MaterialList::get_diffuse(int i) {
00176   return mlist->data(i)->diffuse;
00177 }
00178 
00179 float MaterialList::get_shininess(int i) {
00180   double val = mlist->data(i)->shininess;
00181   return ((float) (log(val/SHINY_A)/SHINY_k + 0.5f)); 
00182 }
00183 
00184 float MaterialList::get_opacity(int i) {
00185   return mlist->data(i)->opacity;
00186 }
00187 
00188 float MaterialList::get_outline(int i) {
00189   return mlist->data(i)->outline;
00190 }
00191 
00192 float MaterialList::get_outlinewidth(int i) {
00193   return mlist->data(i)->outlinewidth;
00194 }
00195 
00196 float MaterialList::get_transmode(int i) {
00197   return mlist->data(i)->transmode;
00198 }
00199 
00200 int MaterialList::delete_material(int n) {
00201   int i, num = mlist->num();
00202   if (n < 2 || n >= num) 
00203     return FALSE;
00204 
00205   NameList<Material *> *newlist = new NameList<Material *>;
00206   for (i=0; i<num; i++) {
00207     Material *mat = mlist->data(i);
00208     if (i == n) {
00209       delete mat;
00210     } else {
00211       mat->ind = newlist->num();   
00212       newlist->add_name(mlist->name(i), mat); 
00213     }
00214   }
00215   delete mlist;
00216   mlist = newlist;
00217 
00218   // notify displayables that material n has been deleted.  Pass reference
00219   // to self so that the displayable can get a new material if it's old
00220   // one was deleted.
00221   root->delete_material(n, this);
00222   return TRUE;
00223 }
00224 
00225 int MaterialList::restore_default(int ind) {
00226   if (ind == 0 || ind == 1) {
00227     Material *mat = mlist->data(ind);
00228     const Material *from = (ind == 0) ? &defOpaque : &defTransp;
00229     memcpy(mat, from, sizeof(Material));
00230     notify(ind);
00231     return TRUE;
00232   }
00233   return FALSE;
00234 }
00235 

Generated on Wed May 22 01:48:39 2013 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002