Main Page   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-2008 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.29 $      $Date: 2008/03/27 19:36:40 $
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      // index
00034 };
00035 
00036 static const Material defTransp = {
00037   0.00f, // ambient
00038   0.50f, // specular
00039   0.65f, // diffuse
00040  40.00f, // shininess 
00041   0.30f, // opacity
00042   1      // index
00043 };
00044 
00045 
00046 // raw shininess values will run from 1 to 1000, but be scaled from 0 to 1
00047 // in the user interface.  If y is the internal value and x is the 
00048 // external (user interface value), then y = A exp(k * (x-0.5)), where...
00049 static const double SHINY_A = sqrt(1000.0);  // ...and...
00050 static const double SHINY_k = log(1000.0);
00051 
00052 MaterialList::MaterialList(Displayable *rootd) : root(rootd) {
00053   mlist = new NameList<Material *>;
00054   Material *opaque, *transp;
00055   opaque = new Material;
00056   transp = new Material;
00057   memcpy(opaque, &defOpaque, sizeof(Material));
00058   memcpy(transp, &defTransp, sizeof(Material));
00059   
00060   // add to list 
00061   mlist->add_name("Opaque",opaque);
00062   mlist->add_name("Transparent",transp);
00063 
00064   // the update_material makes all child displayables update as well; this
00065   // is needed in the case of Scene::root to make sure that Scene::background
00066   // is properly initialized.
00067   root->update_material(material(0));
00068   matcounter = 2;
00069 }
00070 
00071 void MaterialList::notify(int ind) {
00072   const Material *mat = mlist->data(ind);
00073   root->update_material(mat);
00074 }
00075 
00076 MaterialList::~MaterialList() {
00077   for (int i=0; i<mlist->num(); i++) delete mlist->data(i);
00078   delete mlist;
00079 }
00080 
00081 void MaterialList::set_name(int i, const char *nm) {
00082   mlist->set_name(i, nm);
00083 }
00084 
00085 void MaterialList::set_ambient(int i, float f) {
00086   if (i<0 || i >= num()) return;
00087   mlist->data(i)->ambient = f;
00088   notify(i);
00089 }
00090  
00091 void MaterialList::set_specular(int i, float f) {
00092   if (i<0 || i >= num()) return;
00093   mlist->data(i)->specular = f;
00094   notify(i);
00095 }
00096  
00097 void MaterialList::set_diffuse(int i, float f) {
00098   if (i<0 || i >= num()) return;
00099   mlist->data(i)->diffuse = f;
00100   notify(i);
00101 }
00102  
00103 void MaterialList::set_shininess(int i, float f) {
00104   if (i<0 || i >= num()) return;
00105   double val = SHINY_A * exp(SHINY_k * (f-0.5));
00106   mlist->data(i)->shininess = (float) val;
00107   notify(i);
00108 }
00109  
00110 void MaterialList::set_opacity(int i, float f) {
00111   if (i<0 || i >= num()) return;
00112   mlist->data(i)->opacity = f;
00113   notify(i);
00114 }
00115  
00116 const char *MaterialList::add_material(const char *newname, 
00117                                        const char *copyfrom) {
00118   int copyind = 0;
00119   if (copyfrom) {
00120     copyind = material_index(copyfrom);
00121     if (copyind < 0) return NULL;  // material to copy from does not exist
00122   }
00123   char buf[20];
00124   const char *name = newname;
00125   if (!name) {
00126     // find a new unique name.
00127     int id = mlist->num();
00128     do {
00129       sprintf(buf, "Material%d", id++);
00130       name = buf;
00131     } while (mlist->typecode(name) >= 0);
00132   } else {
00133     if (mlist->typecode(name) >= 0)
00134       return NULL; // name already present
00135   }
00136   Material *newmat = new Material;
00137   memcpy(newmat, mlist->data(copyind), sizeof(Material));
00138   newmat->ind = matcounter++;
00139   int ind = mlist->add_name(name, newmat);
00140   return mlist->name(ind);
00141 } 
00142 
00143 float MaterialList::get_ambient(int i) {
00144   return mlist->data(i)->ambient;
00145 }
00146 
00147 float MaterialList::get_specular(int i) {
00148   return mlist->data(i)->specular;
00149 }
00150 
00151 float MaterialList::get_diffuse(int i) {
00152   return mlist->data(i)->diffuse;
00153 }
00154 
00155 float MaterialList::get_shininess(int i) {
00156   double val = mlist->data(i)->shininess;
00157   return ((float) (log(val/SHINY_A)/SHINY_k + 0.5f)); 
00158 }
00159 
00160 float MaterialList::get_opacity(int i) {
00161   return mlist->data(i)->opacity;
00162 }
00163 
00164 int MaterialList::delete_material(int n) {
00165   int i, num = mlist->num();
00166   if (n < 2 || n >= num) 
00167     return FALSE;
00168 
00169   NameList<Material *> *newlist = new NameList<Material *>;
00170   for (i=0; i<num; i++) {
00171     Material *mat = mlist->data(i);
00172     if (i == n) {
00173       delete mat;
00174     } else {
00175       mat->ind = newlist->num();   
00176       newlist->add_name(mlist->name(i), mat); 
00177     }
00178   }
00179   delete mlist;
00180   mlist = newlist;
00181 
00182   // notify displayables that material n has been deleted.  Pass reference
00183   // to self so that the displayable can get a new material if it's old
00184   // one was deleted.
00185   root->delete_material(n, this);
00186   return TRUE;
00187 }
00188 
00189 int MaterialList::restore_default(int ind) {
00190   if (ind == 0 || ind == 1) {
00191     Material *mat = mlist->data(ind);
00192     const Material *from = (ind == 0) ? &defOpaque : &defTransp;
00193     memcpy(mat, from, sizeof(Material));
00194     notify(ind);
00195     return TRUE;
00196   }
00197   return FALSE;
00198 }
00199 

Generated on Fri Aug 29 01:27:03 2008 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002