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
00027
00028 #ifndef SHUTIL_WORLEYIMPL_HPP
00029 #define SHUTIL_WORLEYIMPL_HPP
00030
00031 #include <cstdlib>
00032 #include "ShSyntax.hpp"
00033 #include "ShWorley.hpp"
00034 #include "ShNoise.hpp"
00035 #include "ShFunc.hpp"
00036 #include "ShImage.hpp"
00037 #include "ShTexCoord.hpp"
00038
00039 namespace ShUtil {
00040
00041 using namespace SH;
00042
00043 template<int D, typename T>
00044 void GridGenFactory<D, T>::operator()(const ShGeneric<D, T> &p, Generator<D, T> result[]) const {
00045 ShAttrib<D, SH_TEMP, T> pCell = floor(p);
00046
00047
00048
00049 int i, j, offsetBits;
00050 ShConstAttrib3f offsets(-1, 0, 1);
00051 int offsetSwiz[D];
00052 j = 0;
00053 for(offsetBits = 0; offsetBits < (1 << (D * 2)); ++offsetBits) {
00054 for(i = 0; i < D; ++i) {
00055 offsetSwiz[i] = ((offsetBits >> (i * 2)) & 3);
00056 if(offsetSwiz[i] == 3) break;
00057 }
00058 if(i < D) continue;
00059
00060 Generator<D, T> gen;
00061 result[j].offset = offsets.template swiz<D>(offsetSwiz);
00062 SH_DEBUG_PRINT("Offset:" << result[j].offset);
00063 result[j].cell = pCell + result[j].offset;
00064 makePos(result[j]);
00065 ++j;
00066 }
00067 }
00068
00069
00070 template<int D, typename T>
00071 void DefaultGenFactory<D, T>::makePos(Generator<D, T> &g) const {
00072 g.pos = g.cell + cellnoise<D>(g.cell, m_useTexture);
00073 }
00074
00075 template<int D, typename T>
00076 void NullGenFactory<D, T>::makePos(Generator<D, T> &g) const {
00077 g.pos = g.cell + fillcast<D>(ShAttrib<1, SH_CONST, T>(0.5f));
00078 }
00079
00080 template<int D, typename T>
00081 LerpGenFactory<D, T>::LerpGenFactory(const ShGeneric<1, T> &time, bool useTexture)
00082 : m_time(time), m_useTexture(useTexture) {}
00083
00084 template<int D, typename T>
00085 void LerpGenFactory<D, T>::makePos(Generator<D, T> &g) const {
00086 ShAttrib<1, SH_TEMP, T> lastTime = floor(m_time);
00087 ShAttrib<1, SH_TEMP, T> timeOffset = frac(m_time);
00088 ShAttrib<D + 1, SH_TEMP, T> offsetCell;
00089
00090 offsetCell = fillcast<D+1>(g.cell);
00091 offsetCell(D) = lastTime;
00092 ShAttrib<D, SH_TEMP, T> p1 = cellnoise<D>(offsetCell, m_useTexture);
00093
00094 offsetCell(D) += 1;
00095 ShAttrib<D, SH_TEMP, T> p2 = cellnoise<D>(offsetCell, m_useTexture);
00096
00097 g.pos = g.cell + lerp(timeOffset, p2, p1);
00098 }
00099
00100 template<int N, int D, typename T, typename P1, typename P2>
00101 CombinedPropFactory<N, D, T, P1, P2>::CombinedPropFactory(const P1 *propFactory1, const P2 *propFactory2)
00102 : m_propFactory1(propFactory1), m_propFactory2(propFactory2) {}
00103
00104 template<int N, int D, typename T, typename P1, typename P2>
00105 ShGeneric<N, T> CombinedPropFactory<N, D, T, P1, P2>::operator()(
00106 const ShGeneric<D, T> &p, const Generator<D, T> &g) const {
00107 return join((*m_propFactory1)(p, g), (*m_propFactory2)(p, g));
00108 }
00109
00110 template<typename P1, typename P2>
00111 PropertyFactory<P1::NUM_PROPS + P2::NUM_PROPS, P1::DIM, typename P1::PropType>*
00112 combine(const P1 *propFactory1, const P2 *propFactory2) {
00113 const int N = P1::NUM_PROPS + P2::NUM_PROPS;
00114 return new CombinedPropFactory<N, P1::DIM, typename P1::PropType, P1, P2>(propFactory1, propFactory2);
00115 }
00116
00117 template<int D, typename T>
00118 ShGeneric<1, T> DistSqPropFactory<D, T>::operator()(
00119 const ShGeneric<D, T> &p, const Generator<D, T> &g) const {
00120 ShAttrib<D, SH_TEMP, T> delta = p - g.pos;
00121 return delta | delta;
00122 }
00123
00124 template<int D, typename T>
00125 ShGeneric<1, T> Dist_1PropFactory<D, T>::operator() (
00126 const ShGeneric<D, T> &p, const Generator<D, T> &g) const {
00127 ShAttrib<D, SH_TEMP, T> delta = abs(p - g.pos);
00128 return delta | fillcast<D>(ShConstAttrib1f(1.0f));
00129 }
00130
00131 template<int D, typename T>
00132 ShGeneric<1, T> Dist_InfPropFactory<D, T>::operator() (
00133 const ShGeneric<D, T> &p, const Generator<D, T> &g) const {
00134 ShAttrib<D, SH_TEMP, T> delta = abs(p - g.pos);
00135
00136
00137 ShAttrib<1, SH_TEMP, T> result = 0;
00138 for(int i = 0; i < D; ++i) result = max(result, delta(i));
00139 return result;
00140 }
00141
00142 template<int D, typename T>
00143 ShGeneric<D + 1, T> DistSqGradientPropFactory<D, T>::operator() (
00144 const ShGeneric<D, T> &p, const Generator<D, T> &g) const {
00145 ShAttrib<D + 1, SH_TEMP, T> result;
00146 ShAttrib<D, SH_TEMP, T> delta = p - g.pos;
00147
00148 result(0) = delta | delta;
00149 for(int i = 1; i < D + 1; ++i) {
00150 result(i) = delta(i-1) * result(0);
00151 }
00152 return result;
00153 };
00154
00155 template<int D, typename T>
00156 ShGeneric<D + 1, T> Dist_1GradientPropFactory<D, T>::operator() (
00157 const ShGeneric<D, T> &p, const Generator<D, T> &g) const {
00158
00159 ShAttrib<D + 1, SH_TEMP, T> result;
00160 ShAttrib<D, SH_TEMP, T> delta = p - g.pos;
00161
00162 ShAttrib<1, SH_CONST, T> ONE(1);
00163 result(0) = abs(delta) | fillcast<D>(ONE);
00164 for(int i = 1; i < D + 1; ++i) {
00165 result(i) = cond(delta(i-1), ONE, -ONE);
00166 }
00167 return result;
00168 };
00169
00170 template<int D, typename T>
00171 ShGeneric<D + 1, T> Dist_InfGradientPropFactory<D, T>::operator() (
00172 const ShGeneric<D, T> &p, const Generator<D, T> &g) const {
00173 ShAttrib<D + 1, SH_TEMP, T> result;
00174 ShAttrib<D, SH_TEMP, T> delta = p - g.pos;
00175 ShAttrib<D, SH_TEMP, T> absDelta = abs(delta);
00176
00177 result(0) = 0;
00178 for(int i = 0; i < D; ++i) result(0) = max(result(0), absDelta(i));
00179
00180
00181 ShAttrib<1, SH_CONST, T> ONE(1);
00182 for(int i = 1; i < D + 1; ++i) {
00183 result(i) = (absDelta(i-1) >= result(0)) * cond(delta(i-1), ONE, -ONE);
00184 }
00185 return result;
00186 };
00187
00188 template<int N, int D, typename T>
00189 ShGeneric<N, T> CellnoisePropFactory<N, D, T>::operator() (
00190 const ShGeneric<D, T> &p, const Generator<D, T> &g) const {
00191
00192 return frac(cellnoise<N>(g.cell, m_useTexture));
00193 };
00194
00195 template<typename TexType, typename T>
00196 Tex2DPropFactory<TexType, T>::Tex2DPropFactory(
00197 const ShBaseTexture2D<TexType> &tex, const ShGeneric<1, T> &scale)
00198 : m_tex(tex), m_scale(scale), invScale(ShConstAttrib2f(1.0f, 1.0f) / tex.size()) {}
00199
00200
00201
00202
00203
00204
00205
00206
00207 template<int N, int K, int P, typename T>
00208 void kSelect(const ShGeneric<P, T> vals[N], ShGeneric<K, T> result[N], float LARGE = 1e10) {
00209 result[0] = fillcast<K>(ShConstAttrib1f(LARGE));
00210
00211 int i, j, k, l;
00212 int shiftswiz[K];
00213 ShAttrib1f c;
00214 for(i = 0; i < K; ++i) shiftswiz[i] = (i == 0 ? 0 : i - 1);
00215
00216
00217 for(i = 0; i < P; ++i) {
00218
00219 c = vals[0](i) < result[0](0);
00220 for(j = 0; j < N; ++j) {
00221 result[0] = lerp(c, result[0].template swiz<K>(shiftswiz), result[0]);
00222 result[0](0) = lerp(c, vals[0](i), result[0](0));
00223 }
00224
00225
00226 for(j = 1; j < K; ++j) {
00227 c = (result[0](j-1) < vals[0](i)) * (vals[0](i) < result[0](j));
00228 for(k = 0; k < N; ++k) {
00229 for(l = 0; l < K; ++l) shiftswiz[l] = l + ( l >= j ? -1 : 0);
00230 result[k] = lerp(c, result[k].template swiz<K>(shiftswiz), result[k]);
00231 result[k](j) = lerp(c, vals[k](i), result[k](j));
00232 }
00233 }
00234 }
00235 }
00236
00237 template<int K, int L, int P, int D, typename T>
00238 void worley(ShGeneric<K, T> result[], const ShGeneric<D, T> &p,
00239 const GeneratorFactory<P, D, T> *genFactory,
00240 const PropertyFactory<L, D, T> *propFactory) {
00241
00242 int i, j;
00243 Generator<D, T> generators[P];
00244 ShAttrib<P, SH_TEMP, T> props[L];
00245 ShAttrib<L, SH_TEMP, T> propTemp;
00246
00247 (*genFactory)(p, generators);
00248 for(i = 0; i < P; ++i) {
00249 propTemp = (*propFactory)(p, generators[i]);
00250 for(j = 0; j < L; ++j) props[j](i) = propTemp(j);
00251 }
00252
00253
00254 groupEvenOddSort<L>(props);
00255
00256
00257 for(j = 0; j < L; ++j) result[j] = cast<K>(props[j]);
00258 }
00259
00260 template<int K, int D, typename T>
00261 #ifdef WIn32
00262 ShGeneric<K, T> worley(const ShGeneric<D, T> &p, bool useTexture=true) {
00263 #else
00264 ShGeneric<K, T> worley(const ShGeneric<D, T> &p, bool useTexture=true) {
00265 #endif
00266 DefaultGenFactory<D, T> genFactory(useTexture);
00267 DistSqPropFactory<D, T> propFactory;
00268 ShAttrib<K, SH_TEMP, T> result;
00269 worley(&result, p, &genFactory, &propFactory);
00270 return result;
00271 }
00272
00273 template<int K, int D, typename T>
00274 #ifdef WIn32
00275 ShProgram shWorley(bool useTexture=true) {
00276 #else
00277 ShProgram shWorley(bool useTexture) {
00278 #endif
00279 DefaultGenFactory<D, T> genFactory(useTexture);
00280 DistSqPropFactory<D, T> propFactory;
00281 return shWorley<K>(&genFactory, &propFactory);
00282 }
00283
00284 template<int K, int L, int P, int D, typename T>
00285 ShProgram shWorley(const GeneratorFactory<P, D, T> *genFactory,
00286 const PropertyFactory<L, D, T> *propFactory) {
00287 ShProgram program = SH_BEGIN_PROGRAM() {
00288 ShTexCoord<D, SH_INPUT, T> SH_DECL(texcoord);
00289
00290 ShAttrib<K, SH_OUTPUT, T> result[L];
00291 worley(&result[0], texcoord, genFactory, propFactory);
00292 } SH_END_PROGRAM;
00293 return program;
00294 }
00295
00296 }
00297
00298 #endif