package graphics; import java.awt.image.*; public class Texture { private BufferedImage[] imagePyramid; int w0, h0; //dimensions of source image public Texture(BufferedImage image) { w0 = image.getWidth(null); h0 = image.getHeight(null); //calculate # of steps in pyramid int steps = 1; int w = w0, h = h0; while (w > 1 && h > 1) { w >>= 1; h >>= 1; steps++; } imagePyramid = new BufferedImage[steps]; imagePyramid[0] = image; for (int i=1; i maxS) s = maxS; double t = s - Math.floor(s); //get pyramid images above and below s BufferedImage[] tex = new BufferedImage[2]; tex[0] = imagePyramid[(int)s]; tex[1] = imagePyramid[(int)(s+1)]; int[] width = new int[2], height = new int[2]; //to store interpolated colors at each texture double[][] rgb = {{0, 0, 0}, {0, 0, 0}}; //to store coordinates in actual texture int[] left = new int[2], right = new int[2], top = new int[2], bottom = new int[2]; for (int i=0; i < 2; i++) //get interpolated pixel value for each texture (top and bottom) { width[i] = tex[i].getWidth(null); height[i] = tex[i].getHeight(null); left[i] = (int)(u * width[i]); if (left[i] >= width[i]) left[i] = width[i] - 1; right[i] = left[i] + 1; if (right[i] >= width[i]) right[i] = left[i]; top[i] = (int)(v * height[i]); if (top[i] >= height[i]) top[i] = height[i] - 1; bottom[i] = top[i] + 1; if (bottom[i] >= height[i]) bottom[i] = top[i]; int tl = tex[i].getRGB(left[i], top[i]); int tr = tex[i].getRGB(right[i], top[i]); int bl = tex[i].getRGB(left[i], bottom[i]); int br = tex[i].getRGB(right[i], bottom[i]); //interpolate pixel values at upper and lower levels for (int c=0; c < 3; c++) rgb[i][c] = blerp(u, v, (double)unpack(tl, c), (double)unpack(tr, c), (double)unpack(bl, c), (double)unpack(br, c) ); } //interpolate between two textures int[] RGB = new int[3]; for (int i=0; i < 3; i++) RGB[i] = (int)lerp(t, rgb[0][i], rgb[1][i]); return RGB; } public int getLevels() {return imagePyramid.length;} public int getWidth() {return w0;} public int getHeight() {return h0;} //used for mip-mapping - creates a scaled-down version of image private BufferedImage createHalfImage(BufferedImage src) { int width = src.getWidth(null); int height = src.getHeight(null); int w2 = width/2; int h2 = height/2; BufferedImage image2 = new BufferedImage(w2, h2, BufferedImage.TYPE_INT_RGB); //each pixel in image2 is avg of 4 pixels in src image for (int i = 0; i < w2; i++) for (int j = 0; j < h2; j++) { //get 4 pixels from source image int c0 = src.getRGB(i*2, j*2); int c1 = src.getRGB(i*2 + 1, j*2); int c2 = src.getRGB(i*2, j*2 + 1); int c3 = src.getRGB(i*2 + 1, j*2 + 1); //break up into component rgb int r = unpack(c0, 0) + unpack(c1, 0) + unpack(c2, 0) + unpack(c3, 0); int g = unpack(c0, 1) + unpack(c1, 1) + unpack(c2, 1) + unpack(c3, 1); int b = unpack(c0, 2) + unpack(c1, 2) + unpack(c2, 2) + unpack(c3, 2); int weighted = pack(r/4, g/4, b/4); image2.setRGB(i, j, weighted); } return image2; } //Ken Perlin's code from MISApplet public static int pack(int red, int grn, int blu) { return 255<<24 | clip(red,0,255)<<16 | clip(grn,0,255)<< 8 | clip(blu,0,255) ; } public static int unpack(int packedRGB, int component) { return packedRGB >> 8*(2-component) & 255; } public static int clip(int t, int lo, int hi) { return thi ? hi : t; } private double lerp(double t, double a, double b) { return a + t*(b-a); } //bilinear interpolation between 4 corners private double blerp(double u, double v, double tl, double tr, double bl, double br) { return lerp(v, lerp(u, tl, tr), lerp(u, bl, br)); } }