00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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,
00029 0.50f,
00030 0.65f,
00031 40.00f,
00032 1.00f,
00033 0
00034 };
00035
00036 static const Material defTransp = {
00037 0.00f,
00038 0.50f,
00039 0.65f,
00040 40.00f,
00041 0.30f,
00042 1
00043 };
00044
00045
00046
00047
00048
00049 static const double SHINY_A = sqrt(1000.0);
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
00061 mlist->add_name("Opaque",opaque);
00062 mlist->add_name("Transparent",transp);
00063
00064
00065
00066
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;
00122 }
00123 char buf[20];
00124 const char *name = newname;
00125 if (!name) {
00126
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;
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
00183
00184
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