00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "pbrt.h"
00026 #include "texture.h"
00027 #include "mipmap.h"
00028 #include "paramset.h"
00029 #include <map>
00030 using std::map;
00031
00032 template <class T>
00033 class ImageTexture : public Texture<T> {
00034 public:
00035
00036 ImageTexture(TextureMapping2D *m,
00037 const string &filename,
00038 bool doTri,
00039 float maxAniso,
00040 ImageWrap wm);
00041 T Evaluate(const DifferentialGeometry &) const;
00042 ~ImageTexture();
00043 private:
00044
00045 static MIPMap<T> *GetTexture(const string &filename,
00046 bool doTrilinear, float maxAniso, ImageWrap wm);
00047 static void convert(const Spectrum &from, Spectrum *to) {
00048 *to = from;
00049 }
00050 static void convert(const Spectrum &from, float *to) {
00051 *to = from.y();
00052 }
00053
00054 MIPMap<T> *mipmap;
00055 TextureMapping2D *mapping;
00056 };
00057
00058 template <class T>
00059 ImageTexture<T>::ImageTexture(TextureMapping2D *m,
00060 const string &filename,
00061 bool doTrilinear,
00062 float maxAniso,
00063 ImageWrap wrapMode) {
00064 mapping = m;
00065 mipmap = GetTexture(filename, doTrilinear,
00066 maxAniso, wrapMode);
00067 }
00068 template <class T> ImageTexture<T>::~ImageTexture() {
00069 delete mapping;
00070 }
00071 struct TexInfo {
00072 TexInfo(const string &f, bool dt, float ma, ImageWrap wm)
00073 : filename(f), doTrilinear(dt), maxAniso(ma), wrapMode(wm) { }
00074 string filename;
00075 bool doTrilinear;
00076 float maxAniso;
00077 ImageWrap wrapMode;
00078 bool operator<(const TexInfo &t2) const {
00079 if (filename != t2.filename) return filename < t2.filename;
00080 if (doTrilinear != t2.doTrilinear) return doTrilinear < t2.doTrilinear;
00081 if (maxAniso != t2.maxAniso) return maxAniso < t2.maxAniso;
00082 return wrapMode < t2.wrapMode;
00083 }
00084 };
00085 template <class T> MIPMap<T> *ImageTexture<T>::
00086 GetTexture( const string &filename,
00087 bool doTrilinear,
00088 float maxAniso,
00089 ImageWrap wrap) {
00090
00091 static map<TexInfo, MIPMap<T> *> textures;
00092 TexInfo texInfo(filename, doTrilinear, maxAniso, wrap);
00093 if (textures.find(texInfo) != textures.end())
00094 return textures[texInfo];
00095 static StatsCounter texLoaded("Texture",
00096 "Number of image maps loaded");
00097 ++texLoaded;
00098 int width, height;
00099 Spectrum *texels = ReadImage(filename, &width, &height);
00100 MIPMap<T> *ret = NULL;
00101 if (texels) {
00102
00103 T *convertedTexels = new T[width*height];
00104 for (int i = 0; i < width*height; ++i)
00105 convert(texels[i], &convertedTexels[i]);
00106 ret = new MIPMap<T>(width, height,
00107 convertedTexels, doTrilinear,
00108 maxAniso, wrap);
00109 delete[] texels;
00110 delete[] convertedTexels;
00111 }
00112 else {
00113
00114 T *oneVal = new T[1];
00115 oneVal[0] = 1.;
00116 ret = new MIPMap<T>(1, 1, oneVal);
00117 delete[] oneVal;
00118 }
00119 textures[texInfo] = ret;
00120 return ret;
00121 }
00122 template <class T>
00123 T ImageTexture<T>::Evaluate(
00124 const DifferentialGeometry &dg) const {
00125 float s, t, dsdx, dtdx, dsdy, dtdy;
00126 mapping->Map(dg, &s, &t, &dsdx, &dtdx, &dsdy, &dtdy);
00127 return mipmap->Lookup(s, t, dsdx, dtdx, dsdy, dtdy);
00128 }
00129 extern "C" DLLEXPORT Texture<float> * CreateFloatTexture(const Transform &tex2world,
00130 const TextureParams &tp) {
00131
00132 TextureMapping2D *map = NULL;
00133 string type = tp.FindString("mapping");
00134 if (type == "" || type == "uv") {
00135 float su = tp.FindFloat("uscale", 1.);
00136 float sv = tp.FindFloat("vscale", 1.);
00137 float du = tp.FindFloat("udelta", 0.);
00138 float dv = tp.FindFloat("vdelta", 0.);
00139 map = new UVMapping2D(su, sv, du, dv);
00140 }
00141 else if (type == "spherical") map = new SphericalMapping2D(tex2world.GetInverse());
00142 else if (type == "cylindrical") map = new CylindricalMapping2D(tex2world.GetInverse());
00143 else if (type == "planar")
00144 map = new PlanarMapping2D(tp.FindVector("v1", Vector(1,0,0)),
00145 tp.FindVector("v2", Vector(0,1,0)),
00146 tp.FindFloat("udelta", 0.f), tp.FindFloat("vdelta", 0.f));
00147 else {
00148 Error("2D texture mapping \"%s\" unknown", type.c_str());
00149 map = new UVMapping2D;
00150 }
00151
00152 float maxAniso = tp.FindFloat("maxanisotropy", 8.f);
00153 bool trilerp = tp.FindBool("trilinear", false);
00154 string wrap = tp.FindString("wrap");
00155 ImageWrap wrapMode = TEXTURE_REPEAT;
00156 if (wrap == "" || wrap == "repeat") wrapMode = TEXTURE_REPEAT;
00157 else if (wrap == "black") wrapMode = TEXTURE_BLACK;
00158 else if (wrap == "clamp") wrapMode = TEXTURE_CLAMP;
00159 return new ImageTexture<float>(map, tp.FindString("filename"),
00160 trilerp, maxAniso, wrapMode);
00161 }
00162
00163 extern "C" DLLEXPORT Texture<Spectrum> * CreateSpectrumTexture(const Transform &tex2world,
00164 const TextureParams &tp) {
00165
00166 TextureMapping2D *map = NULL;
00167 string type = tp.FindString("mapping");
00168 if (type == "" || type == "uv") {
00169 float su = tp.FindFloat("uscale", 1.);
00170 float sv = tp.FindFloat("vscale", 1.);
00171 float du = tp.FindFloat("udelta", 0.);
00172 float dv = tp.FindFloat("vdelta", 0.);
00173 map = new UVMapping2D(su, sv, du, dv);
00174 }
00175 else if (type == "spherical") map = new SphericalMapping2D(tex2world.GetInverse());
00176 else if (type == "cylindrical") map = new CylindricalMapping2D(tex2world.GetInverse());
00177 else if (type == "planar")
00178 map = new PlanarMapping2D(tp.FindVector("v1", Vector(1,0,0)),
00179 tp.FindVector("v2", Vector(0,1,0)),
00180 tp.FindFloat("udelta", 0.f), tp.FindFloat("vdelta", 0.f));
00181 else {
00182 Error("2D texture mapping \"%s\" unknown", type.c_str());
00183 map = new UVMapping2D;
00184 }
00185
00186 float maxAniso = tp.FindFloat("maxanisotropy", 8.f);
00187 bool trilerp = tp.FindBool("trilinear", false);
00188 string wrap = tp.FindString("wrap");
00189 ImageWrap wrapMode = TEXTURE_REPEAT;
00190 if (wrap == "" || wrap == "repeat") wrapMode = TEXTURE_REPEAT;
00191 else if (wrap == "black") wrapMode = TEXTURE_BLACK;
00192 else if (wrap == "clamp") wrapMode = TEXTURE_CLAMP;
00193 return new ImageTexture<Spectrum>(map, tp.FindString("filename"),
00194 trilerp, maxAniso, wrapMode);
00195 }