00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "lux.h"
00025 #include "texture.h"
00026 #include "paramset.h"
00027 #include "error.h"
00028
00029 namespace lux {
00030
00031
00032 template <class T>
00033 class BrickTexture3D : public Texture<T> {
00034 public:
00035
00036
00037 virtual ~BrickTexture3D() {
00038 delete mapping;
00039 }
00040
00041 BrickTexture3D(
00042 boost::shared_ptr<Texture<T> > c1,
00043 boost::shared_ptr<Texture<T> > c2,
00044 float brickw,
00045 float brickh,
00046 float brickd,
00047 float mortar,
00048 TextureMapping3D *map) : mapping(map) {
00049 brickwidth = brickw;
00050 brickheight = brickh;
00051 brickdepth = brickd;
00052 mortarsize = mortar;
00053 tex1 = c1;
00054 tex2 = c2;
00055 }
00056
00057 #define BRICK_EPSILON 1e-3f
00058
00059 virtual T Evaluate(const TsPack *tspack, const DifferentialGeometry &dg) const {
00060 Vector dpdx, dpdy;
00061 Point P = mapping->Map(dg, &dpdx, &dpdy);
00062
00063 const float offs = BRICK_EPSILON + mortarsize;
00064 Point bP = P + Point(offs, offs, offs);
00065
00066
00067 float bz = bP.z / brickheight;
00068 int ibz = (int) bz; bz -= ibz;
00069 if (bz < .0f) bz += 1.f;
00070 const float mortarheight = mortarsize / brickheight;
00071 if (bz <= mortarheight)
00072 return tex2->Evaluate(tspack, dg);
00073 bz = (bP.z / brickheight) * .5f;
00074 ibz = (int) bz; bz -= ibz;
00075 if (bz < .0f) bz += 1.f;
00076
00077
00078 float bx = bP.x / brickwidth;
00079 int ibx = (int) bx; bx -= ibx;
00080 if (bx < .0f) bx += 1.f;
00081 const float mortarwidth = mortarsize / brickwidth;
00082 if ((bx <= mortarwidth) && (bz <= .5f))
00083 return tex2->Evaluate(tspack, dg);
00084
00085
00086 bx = (bP.x / brickwidth) + .5f;
00087 ibx = (int) bx; bx -= ibx;
00088 if (bx < .0f) bx += 1.f;
00089 if ((bx <= mortarwidth) && (bz > .5f))
00090 return tex2->Evaluate(tspack, dg);
00091
00092
00093 float by = bP.y / brickdepth;
00094 int iby = (int) by; by -= iby;
00095 if (by < .0f) by += 1.f;
00096 const float mortardepth = mortarsize / brickdepth;
00097 if ((by <= mortardepth) && (bz > .5f))
00098 return tex2->Evaluate(tspack, dg);
00099
00100
00101 by = (bP.y / brickdepth) + .5f;
00102 iby = (int) by; by -= iby;
00103 if (by < .0f) by += 1.f;
00104 if ((by <= mortardepth) && (bz <= .5f))
00105 return tex2->Evaluate(tspack, dg);
00106
00107
00108 return tex1->Evaluate(tspack, dg);
00109 }
00110 virtual void SetPower(float power, float area) {
00111
00112 tex1->SetPower(power, area);
00113 tex2->SetPower(power, area);
00114 }
00115 virtual void SetIlluminant() {
00116
00117 tex1->SetIlluminant();
00118 tex2->SetIlluminant();
00119 }
00120 static Texture<float> *CreateFloatTexture(const Transform &tex2world, const TextureParams &tp);
00121 static Texture<SWCSpectrum> *CreateSWCSpectrumTexture(const Transform &tex2world, const TextureParams &tp);
00122 private:
00123
00124 float brickwidth, brickheight, brickdepth, mortarsize;
00125 TextureMapping3D *mapping;
00126 boost::shared_ptr<Texture<T> > tex1, tex2;
00127 };
00128
00129 template <class T> Texture<float> *BrickTexture3D<T>::CreateFloatTexture(
00130 const Transform &tex2world,
00131 const TextureParams &tp) {
00132
00133 TextureMapping3D *map = new IdentityMapping3D(tex2world);
00134
00135 IdentityMapping3D *imap = (IdentityMapping3D*) map;
00136 imap->Apply3DTextureMappingOptions(tp);
00137
00138 boost::shared_ptr<Texture<float> > tex1 = tp.GetFloatTexture("bricktex", 1.f);
00139 boost::shared_ptr<Texture<float> > tex2 = tp.GetFloatTexture("mortartex", 0.2f);
00140
00141 float bw = tp.FindFloat("brickwidth", 0.3f);
00142 float bh = tp.FindFloat("brickheight", 0.1f);
00143 float bd = tp.FindFloat("brickdepth", 0.15f);
00144
00145 float m = tp.FindFloat("mortarsize", 0.01f);
00146
00147 return new BrickTexture3D<float>(tex1, tex2, bw, bh, bd, m, map);
00148 }
00149
00150 template <class T> Texture<SWCSpectrum> *BrickTexture3D<T>::CreateSWCSpectrumTexture(
00151 const Transform &tex2world,
00152 const TextureParams &tp) {
00153
00154 TextureMapping3D *map = new IdentityMapping3D(tex2world);
00155
00156 IdentityMapping3D *imap = (IdentityMapping3D*) map;
00157 imap->Apply3DTextureMappingOptions(tp);
00158
00159 boost::shared_ptr<Texture<SWCSpectrum> > tex1 = tp.GetSWCSpectrumTexture("bricktex", 1.f);
00160 boost::shared_ptr<Texture<SWCSpectrum> > tex2 = tp.GetSWCSpectrumTexture("mortartex", 0.2f);
00161
00162 float bw = tp.FindFloat("brickwidth", 0.3f);
00163 float bh = tp.FindFloat("brickheight", 0.1f);
00164 float bd = tp.FindFloat("brickdepth", 0.15f);
00165
00166 float m = tp.FindFloat("mortarsize", 0.01f);
00167
00168 return new BrickTexture3D<SWCSpectrum>(tex1, tex2, bw, bh, bd, m, map);
00169 }
00170
00171 }