crt/texture.cpp
#include "texture.hpp"
Texture::Texture(bool b, unsigned r): need_coords(b), radiosity(MIN(MAX(r, 0), 100)/100.0) {
}
Texture::~Texture() {
}
ColorTexture::ColorTexture(unsigned r, const Img::rgb_t& c): Texture(false, r), col(c) {
}
bool ColorTexture::max_dim(unsigned&, unsigned&) const {
return false;
}
INLINE const Img::rgb_t& ColorTexture::get() const {
return col;
}
INLINE const Img::rgb_t& ColorTexture::get(coord_t, coord_t) const {
return get();
}
INLINE Img::rgb_t ColorTexture::get_uv(coord_t, coord_t) const {
return get();
}
DummyTexture::DummyTexture(unsigned r): Texture(true, r), width(4), b(255,0,0), w(0,255,0) {
}
DummyTexture::DummyTexture(unsigned r, const Img::rgb_t bb, Img::rgb_t ww, unsigned w): Texture(true, r), width(w), b(bb), w(ww) {
}
bool DummyTexture::max_dim(unsigned&, unsigned&) const {
return false;
}
INLINE const Img::rgb_t& DummyTexture::get() const {
return b;
}
INLINE const Img::rgb_t& DummyTexture::get(coord_t x, coord_t y) const {
const int xr = lround(x) / width;
const int yr = lround(y) / width;
return (xr % 2 != yr % 2)? b: w;
}
INLINE Img::rgb_t DummyTexture::get_uv(coord_t u, coord_t v) const { // ignores width
assert(u >= 0.0 && u <= 1.0);
assert(v >= 0.0 && v <= 1.0);
return ((u <= 0.5) != (v <= 0.5))? b: w;
}
ImageTexture::ImageTexture(unsigned r, Img* i): Texture(true, r), img(i), avgcol(i->avg(0, 0, i->w, i->h)) {
}
bool ImageTexture::max_dim(unsigned& w, unsigned& h) const {
w = img->w;
h = img->h;
return true;
}
ImageTexture::~ImageTexture() {
delete img;
}
Texture* ImageTexture::load(unsigned r, const char* fn, const char* mod) {
if (mod) {
if (mod[0] < '0' || mod[0] > '3') return (Texture*)(new DummyTexture(r));
if (mod[1] != 'x' && mod[1] != 'y' && mod[1] != '\0') return (Texture*)(new DummyTexture(r));
}
Img* i = Img::from_ppm(fn);
if (!i) {
return (Texture*)new DummyTexture(r);
}
if (mod) {
for (int r=0; r<mod[0]-'0'; ++r) {
Img* tmp = i->rotate();
delete i;
i = tmp;
}
if (mod[1] == 'x') {
i->mirror_x();
} else if (mod[1] == 'y') {
i->mirror_y();
}
}
return (Texture*)new ImageTexture(r, i);
}
INLINE const Img::rgb_t& ImageTexture::get() const {
return avgcol;
}
const Img::rgb_t& ImageTexture::get(coord_t x, coord_t y) const {
return img->at(lround(x) % img->w, lround(y) % img->h);
}
INLINE Img::rgb_t ImageTexture::get_uv(coord_t u, coord_t v) const {
assert(u >= 0.0 && u <= 1.0);
assert(v >= 0.0 && v <= 1.0);
return img->interpolate(u*(img->w-1), v*(img->h-1));
}