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.00f,
00034 0.00f,
00035 0.00f,
00036 0
00037 };
00038
00039 static const Material defTransp = {
00040 0.00f,
00041 0.50f,
00042 0.65f,
00043 40.00f,
00044 0.30f,
00045 0.00f,
00046 0.00f,
00047 0.00f,
00048 1
00049 };
00050
00051
00052
00053
00054
00055 static const double SHINY_A = sqrt(1000.0);
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
00067 mlist->add_name("Opaque",opaque);
00068 mlist->add_name("Transparent",transp);
00069
00070
00071
00072
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;
00146 }
00147 char buf[20];
00148 const char *name = newname;
00149 if (!name) {
00150
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;
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
00219
00220
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