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 0.00f,
00033 1.00f,
00034 0.00f,
00035 0.00f,
00036 0.00f,
00037 0
00038 };
00039
00040 static const Material defTransp = {
00041 0.00f,
00042 0.50f,
00043 0.65f,
00044 40.00f,
00045 0.00f,
00046 0.30f,
00047 0.00f,
00048 0.00f,
00049 0.00f,
00050 1
00051 };
00052
00053
00054
00055
00056
00057 static const double SHINY_A = sqrt(1000.0);
00058 static const double SHINY_k = log(1000.0);
00059
00060 MaterialList::MaterialList(Displayable *rootd) : root(rootd) {
00061 mlist = new NameList<Material *>;
00062 Material *opaque, *transp;
00063 opaque = new Material;
00064 transp = new Material;
00065 memcpy(opaque, &defOpaque, sizeof(Material));
00066 memcpy(transp, &defTransp, sizeof(Material));
00067
00068
00069 mlist->add_name("Opaque",opaque);
00070 mlist->add_name("Transparent",transp);
00071
00072
00073
00074
00075 root->update_material(material(0));
00076 matcounter = 2;
00077 }
00078
00079 void MaterialList::notify(int ind) {
00080 const Material *mat = mlist->data(ind);
00081 root->update_material(mat);
00082 }
00083
00084 MaterialList::~MaterialList() {
00085 for (int i=0; i<mlist->num(); i++) delete mlist->data(i);
00086 delete mlist;
00087 }
00088
00089 void MaterialList::set_name(int i, const char *nm) {
00090 mlist->set_name(i, nm);
00091 }
00092
00093 void MaterialList::set_ambient(int i, float f) {
00094 if (i<0 || i >= num()) return;
00095 mlist->data(i)->ambient = f;
00096 notify(i);
00097 }
00098
00099 void MaterialList::set_specular(int i, float f) {
00100 if (i<0 || i >= num()) return;
00101 mlist->data(i)->specular = f;
00102 notify(i);
00103 }
00104
00105 void MaterialList::set_diffuse(int i, float f) {
00106 if (i<0 || i >= num()) return;
00107 mlist->data(i)->diffuse = f;
00108 notify(i);
00109 }
00110
00111 void MaterialList::set_shininess(int i, float f) {
00112 if (i<0 || i >= num()) return;
00113 double val = SHINY_A * exp(SHINY_k * (f-0.5));
00114 mlist->data(i)->shininess = (float) val;
00115 notify(i);
00116 }
00117
00118 void MaterialList::set_mirror(int i, float f) {
00119 if (i<0 || i >= num()) return;
00120 mlist->data(i)->mirror = f;
00121 notify(i);
00122 }
00123
00124 void MaterialList::set_opacity(int i, float f) {
00125 if (i<0 || i >= num()) return;
00126 mlist->data(i)->opacity = f;
00127 notify(i);
00128 }
00129
00130 void MaterialList::set_outline(int i, float f) {
00131 if (i<0 || i >= num()) return;
00132 mlist->data(i)->outline = f;
00133 notify(i);
00134 }
00135
00136 void MaterialList::set_outlinewidth(int i, float f) {
00137 if (i<0 || i >= num()) return;
00138 mlist->data(i)->outlinewidth = f;
00139 notify(i);
00140 }
00141
00142 void MaterialList::set_transmode(int i, float f) {
00143 if (i<0 || i >= num()) return;
00144 mlist->data(i)->transmode = f;
00145 notify(i);
00146 }
00147
00148 const char *MaterialList::add_material(const char *newname,
00149 const char *copyfrom) {
00150 int copyind = 0;
00151 if (copyfrom) {
00152 copyind = material_index(copyfrom);
00153 if (copyind < 0) return NULL;
00154 }
00155 char buf[20];
00156 const char *name = newname;
00157 if (!name) {
00158
00159 int id = mlist->num();
00160 do {
00161 sprintf(buf, "Material%d", id++);
00162 name = buf;
00163 } while (mlist->typecode(name) >= 0);
00164 } else {
00165 if (mlist->typecode(name) >= 0)
00166 return NULL;
00167 }
00168 Material *newmat = new Material;
00169 memcpy(newmat, mlist->data(copyind), sizeof(Material));
00170 newmat->ind = matcounter++;
00171 int ind = mlist->add_name(name, newmat);
00172 return mlist->name(ind);
00173 }
00174
00175 float MaterialList::get_ambient(int i) {
00176 return mlist->data(i)->ambient;
00177 }
00178
00179 float MaterialList::get_specular(int i) {
00180 return mlist->data(i)->specular;
00181 }
00182
00183 float MaterialList::get_diffuse(int i) {
00184 return mlist->data(i)->diffuse;
00185 }
00186
00187 float MaterialList::get_shininess(int i) {
00188 double val = mlist->data(i)->shininess;
00189 return ((float) (log(val/SHINY_A)/SHINY_k + 0.5f));
00190 }
00191
00192 float MaterialList::get_mirror(int i) {
00193 return mlist->data(i)->mirror;
00194 }
00195
00196 float MaterialList::get_opacity(int i) {
00197 return mlist->data(i)->opacity;
00198 }
00199
00200 float MaterialList::get_outline(int i) {
00201 return mlist->data(i)->outline;
00202 }
00203
00204 float MaterialList::get_outlinewidth(int i) {
00205 return mlist->data(i)->outlinewidth;
00206 }
00207
00208 float MaterialList::get_transmode(int i) {
00209 return mlist->data(i)->transmode;
00210 }
00211
00212 int MaterialList::delete_material(int n) {
00213 int i, num = mlist->num();
00214 if (n < 2 || n >= num)
00215 return FALSE;
00216
00217 NameList<Material *> *newlist = new NameList<Material *>;
00218 for (i=0; i<num; i++) {
00219 Material *mat = mlist->data(i);
00220 if (i == n) {
00221 delete mat;
00222 } else {
00223 mat->ind = newlist->num();
00224 newlist->add_name(mlist->name(i), mat);
00225 }
00226 }
00227 delete mlist;
00228 mlist = newlist;
00229
00230
00231
00232
00233 root->delete_material(n, this);
00234 return TRUE;
00235 }
00236
00237 int MaterialList::restore_default(int ind) {
00238 if (ind == 0 || ind == 1) {
00239 Material *mat = mlist->data(ind);
00240 const Material *from = (ind == 0) ? &defOpaque : &defTransp;
00241 memcpy(mat, from, sizeof(Material));
00242 notify(ind);
00243 return TRUE;
00244 }
00245 return FALSE;
00246 }
00247