// // texture.cc // // Various texture functions // // Copyright (C) J. Belson 2000.02.08 // // $Author: jon $ : $Date: 2003/10/11 18:11:00 $ // // Mostly based on examples from "Texturing and Modeling" #include #include #include #include "perlin2.h" #include "settings.h" #include "texture.h" #include "hf.h" /** * Constructor */ texture::texture(const textset& ts) { fg = ts.fg; bg = ts.bg; } /** * Chessboard texture */ fcolour texture_chessboard::colour(float s, float t, float, vector3d*) { const float CHECK_SIZE = 0.5; float ss = s/(2*CHECK_SIZE); float tt = t/(2*CHECK_SIZE); float sbrick = std::floor(ss); float tbrick = std::floor(tt); ss -= sbrick; tt -= tbrick; int a = texture::step(0.5, ss) - texture::step(1.0, ss); int b = texture::step(0.5, tt) - texture::step(1.0, tt); if (a^b) { return fcolour(0xa0/255.0, 0xa0/255.0, 0xa0/255.0); } else { return fcolour(1.0, 0.0, 0.0); } } /** * Brick wall texture */ fcolour texture_brickwall::colour(float s, float t, float, vector3d*) { const float BRICK_WIDTH = 0.6; const float BRICK_HEIGHT = 0.2; const float CONCRETE = 0.04; const float FULL_WIDTH = BRICK_WIDTH + CONCRETE; const float FULL_HEIGHT = BRICK_HEIGHT + CONCRETE; const float CONCRETE_W_RATIO = (CONCRETE*0.5)/FULL_WIDTH; const float CONCRETE_H_RATIO = (CONCRETE*0.5)/FULL_HEIGHT; s /= 35; t /= 35; float ss = s/(FULL_WIDTH); float tt = t/(FULL_HEIGHT); // Alternate rows shifted if (texture::mod(tt * 0.5, 1.0) > 0.5) { ss += 0.5; } float sbrick = floor(ss); float tbrick = floor(tt); ss -= sbrick; tt -= tbrick; int a = texture::step(CONCRETE_W_RATIO, ss) - texture::step(1 - CONCRETE_W_RATIO, ss); int b = texture::step(CONCRETE_H_RATIO, tt) - texture::step(1 - CONCRETE_H_RATIO, tt); if (a*b) { return fcolour(1.0, 0.0, 0.0); } else { return fcolour(0xa0/255.0, 0xa0/255.0, 0xa0/255.0); } } /** * Repeating spheres pattern */ fcolour texture_spheres::colour(float s, float t, float, vector3d*) { s /= 20; t /= 20; const float RADIUS = 0.15; float ss = s/1.0; float tt = t/1.0; ss -= floor(ss); tt -= floor(tt); ss -= 0.5; tt -= 0.5; if (ss*ss + tt*tt < RADIUS) { return fcolour(0.0, 0.0, 1.0); } else { return fcolour(0.0, 1.0, 1.0); } } /** * Strata effect */ static fcolour col_array[] = { fcolour(166/255.0, 131/255.0, 70/255.0), fcolour(166/255.0, 131/255.0, 70/255.0), fcolour(204/255.0, 178/255.0, 127/255.0), fcolour(184/255.0, 153/255.0, 97/255.0), fcolour(140/255.0, 114/255.0, 51/255.0), fcolour(159/255.0, 123/255.0, 60/255.0), fcolour(204/255.0, 178/255.0, 127/255.0), fcolour(230/255.0, 180/255.0, 80/255.0), fcolour(192/255.0, 164/255.0, 110/255.0), fcolour(172/255.0, 139/255.0, 80/255.0), fcolour(102/255.0, 76/255.0, 25/255.0), fcolour(166/255.0, 131/255.0, 70/255.0), fcolour(201/255.0, 175/255.0, 124/255.0), fcolour(181/255.0, 150/255.0, 94/255.0), fcolour(161/255.0, 125/255.0, 64/255.0), fcolour(177/255.0, 145/255.0, 87/255.0), fcolour(170/255.0, 136/255.0, 77/255.0), fcolour(197/255.0, 170/255.0, 117/255.0), fcolour(180/255.0, 100/255.0, 50/255.0), fcolour(175/255.0, 142/255.0, 84/255.0), fcolour(197/255.0, 170/255.0, 117/255.0), fcolour(177/255.0, 145/255.0, 87/255.0), fcolour(170/255.0, 136/255.0, 77/255.0), fcolour(186/255.0, 156/255.0, 100/255.0), fcolour(166/255.0, 131/255.0, 70/255.0), fcolour(188/255.0, 159/255.0, 104/255.0), fcolour(168/255.0, 134/255.0, 74/255.0), fcolour(159/255.0, 123/255.0, 60/255.0), fcolour(195/255.0, 167/255.0, 114/255.0), fcolour(175/255.0, 142/255.0, 84/255.0), fcolour(161/255.0, 125/255.0, 64/255.0), fcolour(197/255.0, 170/255.0, 117/255.0), fcolour(177/255.0, 145/255.0, 87/255.0), fcolour(177/255.0, 145/255.0, 87/255.0) }; texture_strata::texture_strata(const textset& ts) : texture(ts) { noise = new perlin2; } fcolour texture_strata::colour(float s, float t, float u, vector3d*) { float h = u/4; ///20.0; h += noise->noise2(s/50, t/50)*2; while (h>1) { h -= 1; } fcolour c = texture::spline(h, sizeof(col_array)/sizeof(col_array[0]), col_array); return c; } texture_strata::~texture_strata() { delete noise; } /** * Blend two floating point numbers * @param n1 First number * @param n2 Second number * @param f Ratio (0.0 >= f <= 1.0) */ float texture::mix(float n1, float n2, float f) { return (1.0-f)* n1 + f*n2; } /** * Blend two colours * @param c1 First colour * @param c2 Second colour * @param f Ratio (0.0 >= f <= 1.0) */ fcolour texture::mix(fcolour c1, fcolour c2, float f) { return c1*(1.0-f) + c2*f; } /** * Stepping function * @return false when x < a, else true */ int texture::step(float a, float x) { return (x >= a); } /** * Cubic interpolatated step function * @return 0 for n < a, 1 for n >= b or interpolated value if a <= n < b */ float texture::smooth_step(float n, float a, float b) { #if 0 float val; if (n < a) { val = a; } else if (n > b) { val = b; } else { n = (n - a)*(b - a); // Normalise to 0->1 val = (n*n*(3 - 2*n)); } return val; #endif float val; if (n < a) { val = 0; } else if (n >= b) { val = 1; } else { n = (n - a)*(b - a); // Normalise to 0->1 val = (n*n*(3 - 2*n)); } return val; } /** * Rectangular pulse, beginning at x==a and ending at x==b */ int texture::pulse(float a, float b, float x) { return step(a, x) - step(b, x); } /** * Return n when between a and b, a for lt, b for gt */ float texture::clamp(float n, float a, float b) { float val; if (n < a) { val = a; } else if (n > b) { val = b; } else { val = n; } return val; } /** * Return smaller of two arguments */ float texture::min(float n, float a) { return (n < a) ? n : a; } /** * Return larger of two arguments */ float texture::max(float n, float a) { return (n > a) ? n : a; } /** * Same as math.h function */ float texture::abs(float n) { return (n > 0) ? n : -n; } /** * Modulus function, rather than C style remainder */ float texture::mod(float n, float a) { int val = int (n/a); n -= val * a; if (n < 0) { n += a; } return n; } /** * Gamma correction function */ float texture::gamma_correct(float gamma, float n) { //return pow(double(n), double(1.0/gamma)); return std::pow(double (n), double(1.0/gamma)); } /** * Remapping function for unit interval */ float texture::bias(float b, float n) { //return pow(double(n), double(log(b)/log(0.5))); return std::pow(double(n), double(log(b)/log(0.5))); } /** * Remapping function for unit interval */ float texture::gain(float g, float n) { float val; if (n < 0.5) { val = bias(1.0 - g, 2.0*n)/2.0; } else { val = 1 - bias(1.0 - g, 2.0 - 2.0*n)/2.0; } return val; }