getPixel() public method

public getPixel ( int x, int y ) : float
x int
y int
return float
Ejemplo n.º 1
0
		public Channel channelDifference(Channel channel) {
			for (int y = 0; y < height; y++) {
				for (int x = 0; x < width; x++) {
					putPixel(x, y, Math.Abs(getPixel(x, y) - channel.getPixel(x, y)));
				}
			}
			return this;
		}
Ejemplo n.º 2
0
		public Channel channelBrightest(Channel channel) {
			for (int y = 0; y < height; y++) {
				for (int x = 0; x < width; x++) {
					putPixel(x, y, Math.Max(getPixel(x, y), channel.getPixel(x, y)));
				}
			}
			return this;
		}	
Ejemplo n.º 3
0
		public Channel channelMultiply(Channel channel) {
			for (int y = 0; y < height; y++) {
				for (int x = 0; x < width; x++) {
					putPixel(x, y, getPixel(x, y) * channel.getPixel(x, y));
				}
			}
			return this;
		}
Ejemplo n.º 4
0
		public Channel channelDivide(Channel channel) {
			for (int y = 0; y < height; y++) {
				for (int x = 0; x < width; x++) {
					putPixel(x, y, getPixel(x, y) / channel.getPixel(x, y));
				}
			}
			return this;
		}
Ejemplo n.º 5
0
 public Layer bump(Channel bumpmap, float lx, float ly, float shadow, float light_r, float light_g, float light_b, float ambient_r, float ambient_g, float ambient_b)
 {
     if(!(bumpmap.getWidth() == width && bumpmap.getHeight() == height))
         throw new Exception("bumpmap size does not match layer size");
     for (int y = 0; y < height; y++) {
         for (int x = 0; x < width; x++) {
             float nx = bumpmap.getPixelWrap(x + 1, y) - bumpmap.getPixelWrap(x - 1, y);
             float ny = bumpmap.getPixelWrap(x, y + 1) - bumpmap.getPixelWrap(x, y - 1);
             float brightness = nx*lx + ny*ly;
             if (brightness >= 0) {
                 putPixelClip(x, y, (r.getPixel(x, y) + brightness*light_r)*(bumpmap.getPixel(x, y)*shadow + 1 - shadow),
                     (g.getPixel(x, y) + brightness*light_g)*(bumpmap.getPixel(x, y)*shadow + 1 - shadow),
                     (b.getPixel(x, y) + brightness*light_b)*(bumpmap.getPixel(x, y)*shadow + 1 - shadow));
             } else {
                 putPixelClip(x, y, (r.getPixel(x, y) + brightness*(1 - ambient_r))*(bumpmap.getPixel(x, y)*shadow + 1 - shadow),
                     (g.getPixel(x, y) + brightness*(1 - ambient_g))*(bumpmap.getPixel(x, y)*shadow + 1 - shadow),
                     (b.getPixel(x, y) + brightness*(1 - ambient_b))*(bumpmap.getPixel(x, y)*shadow + 1 - shadow));
             }
         }
     }
     return this;
 }
Ejemplo n.º 6
0
        public static Channel erode4(Channel channel, float rain_amount, float vaporization, int rain_freq, int iterations)
        {
            Channel water_map = new Channel(channel.width, channel.height).fill(0f);
            Channel water_map_diff = new Channel(channel.width, channel.height).fill(0f);
            Channel height_map_diff = new Channel(channel.width, channel.height).fill(0f);

            Console.Write("Hydraulic erosion 4: ");

            for (int i = 0; i < iterations; i++) {

                Console.Write(".");

                // save frames
                /*
                if (channel.width > 128 && i%10 == 0) {
                    if (i < 10) {
                        channel.toLayer().saveAsPNG("erosion00" + i);
                    } else if (i < 100) {
                        channel.toLayer().saveAsPNG("erosion0" + i);
                    } else {
                        channel.toLayer().saveAsPNG("erosion" + i);
                    }
                }
                */

                // rain erodes the underlying terrain
                if (i%rain_freq == 0) {
                    water_map.channelAdd(channel.copy().multiply(rain_amount));
                }

                // water and sediment transport
                for (int y = 1; y < channel.height - 1; y++) {
                    for (int x = 1; x < channel.width - 1; x++) {

                        // calculate total heights and height differences
                        float h = channel.getPixel(x, y) + water_map.getPixel(x, y);

                        float h1 = channel.getPixel(x, y + 1) + water_map.getPixel(x, y + 1);
                        float h2 = channel.getPixel(x - 1, y) + water_map.getPixel(x - 1, y);
                        float h3 = channel.getPixel(x + 1, y) + water_map.getPixel(x + 1, y);
                        float h4 = channel.getPixel(x, y - 1) + water_map.getPixel(x, y - 1);

                        float d1 = h - h1;
                        float d2 = h - h2;
                        float d3 = h - h3;
                        float d4 = h - h4;

                        // calculate amount of water to transport
                        float total_height = 0;
                        float total_height_diff = 0;
                        int cells = 1;

                        if (d1 > 0) {
                            total_height_diff+= d1;
                            total_height+= h1;
                            cells++;
                        }
                        if (d2 > 0) {
                            total_height_diff+= d2;
                            total_height+= h2;
                            cells++;
                        }
                        if (d3 > 0) {
                            total_height_diff+= d3;
                            total_height+= h3;
                            cells++;
                        }
                        if (d4 > 0) {
                            total_height_diff+= d4;
                            total_height+= h4;
                            cells++;
                        }

                        if (cells == 1) {
                            continue;
                        }

                        float avr_height = total_height/cells;
                        float water_amount = Math.Min(water_map.getPixel(x, y), h - avr_height);
                        water_map_diff.putPixel(x, y, water_map_diff.getPixel(x, y) - water_amount);
                        float total_height_diff_inv = water_amount/total_height_diff;

                        // transport water
                        if (d1 > 0) {
                            water_amount = d1*total_height_diff_inv;
                            water_map_diff.putPixel(x, y + 1, water_map_diff.getPixel(x, y + 1) + water_amount);
                            height_map_diff.putPixel(x, y + 1, height_map_diff.getPixel(x, y + 1) - 0.1f*water_amount);
                        }
                        if (d2 > 0) {
                            water_amount = d2*total_height_diff_inv;
                            water_map_diff.putPixel(x - 1, y, water_map_diff.getPixel(x - 1, y) + water_amount);
                            height_map_diff.putPixel(x - 1, y, height_map_diff.getPixel(x - 1, y) - 0.1f*water_amount);
                        }
                        if (d3 > 0) {
                            water_amount = d3*total_height_diff_inv;
                            water_map_diff.putPixel(x + 1, y, water_map_diff.getPixel(x + 1, y) + water_amount);
                            height_map_diff.putPixel(x + 1, y, height_map_diff.getPixel(x + 1, y) - 0.1f*water_amount);
                        }
                        if (d4 > 0) {
                            water_amount = d4*total_height_diff_inv;
                            water_map_diff.putPixel(x, y - 1, water_map_diff.getPixel(x, y - 1) + water_amount);
                            height_map_diff.putPixel(x, y - 1, height_map_diff.getPixel(x, y - 1) - 0.1f*water_amount);
                        }
                    }
                }

                // apply changes to water map
                water_map.channelAddNoClip(water_map_diff);
                water_map_diff.fill(0f);

                // apply changes to height map
                channel.channelAddNoClip(height_map_diff);
                height_map_diff.fill(0f);

                // vaporize water
                channel.channelAddNoClip(water_map.copy().channelSubtract(water_map.addClip(-vaporization)).multiply(0.5f));
            }

            // force evaporation of remaining water
            channel.channelAdd(water_map.multiply(0.5f));

            Console.WriteLine("DONE");

            return channel;
        }
Ejemplo n.º 7
0
		public Channel channelBlend(Channel channel, Channel alpha) {
			for (int y = 0; y < height; y++) {
				for (int x = 0; x < width; x++) {
					float alpha_val = alpha.getPixel(x, y);
					putPixel(x, y, alpha_val*channel.getPixel(x, y) + (1 - alpha_val)*getPixel(x, y));
				}
			}
			return this;
		}
Ejemplo n.º 8
0
        private void Gen(int sizeX, int sizeY, int base_freq, float pers, long seed, int x_o, int y_o)
        {
            if (!Utils.isPowerOf2(sizeX))
                throw new Exception("sizeX must be power of 2");
            if (!Utils.isPowerOf2(sizeY))
                throw new Exception("sizeY must be power of 2");

            int iterationsX = Utils.powerOf2Log2(sizeX);
            int iterationsY = Utils.powerOf2Log2(sizeY);
            base_freq = Math.Max(base_freq, 0);
            base_freq = Math.Min(base_freq, iterationsX);
            random = new Random((int)seed);
            channel = new Channel(sizeX, sizeY);

            int x_block, y_block, x, y;

            if (base_freq > 0) {
                int block_size = sizeX>>base_freq;
                for (int x_b = 0; x_b < (1<<base_freq); x_b++) {
                    for (int y_b = 0; y_b < (1<<base_freq); y_b++) {
                        x = x_b*block_size;
                        y = y_b*block_size;
                        channel.putPixel(x, y, (float)random.NextDouble());
                    }
                }
            }

            float v1, v2, v3, v4, v5, v6, v7, v8, v9;

            for (int i = base_freq; i < iterationsX; i++) {
                int block_size = sizeX>>i;
                int block_size_half = sizeX>>(i + 1);
                float amp = (float)Math.Pow(pers, i - base_freq);
                float amp_half = 0.5f*amp;
                float avr;
                // calculate center midpoints
                if (i < 2) {
                    for (x_block = 0, x = 0; x_block < (1<<i); x_block++) {
                        for (y_block = 0, y = 0; y_block < (1<<i); y_block++) {
                            v1 = channel.getPixel(x, y);
                            v2 = channel.getPixel((x + block_size) % sizeX, y);
                            v3 = channel.getPixel(x, (y + block_size) % sizeY);
                            v4 = channel.getPixel((x + block_size) % sizeX, (y + block_size) % sizeY);
                            avr = 0.25f*(v1 + v2 + v3 + v4);
                            v5 = avr*(1f + (float)random.NextDouble()*amp - amp_half);
                            channel.putPixel(x + block_size_half, y + block_size_half, v5);
                            y+= block_size;
                        }
                        x+= block_size;
                    }
                } else {
                    // safe blocks
                    for (x_block = 1, x = block_size; x_block < (1<<i) - 1; x_block++) {
                        for (y_block = 1, y = block_size; y_block < (1<<i) - 1; y_block++) {
                            v1 = channel.getPixel(x, y);
                            v2 = channel.getPixel(x + block_size, y);
                            v3 = channel.getPixel(x, y + block_size);
                            v4 = channel.getPixel(x + block_size, y + block_size);
                            avr = 0.25f*(v1 + v2 + v3 + v4);
                            v5 = avr*(1f + (float)random.NextDouble()*amp - amp_half);
                            channel.putPixel(x + block_size_half, y + block_size_half, v5);
                            y+= block_size;
                        }
                        x+= block_size;
                    }
                    // left and right edge blocks
                    for (x_block = 0; x_block < (1<<i); x_block+= (1<<i) - 1) {
                        x = x_block*block_size;
                        for (y_block = 0, y = 0; y_block < (1<<i); y_block++) {
                            v1 = channel.getPixel(x, y);
                            v2 = channel.getPixel((x + block_size) % sizeX, y);
                            v3 = channel.getPixel(x, (y + block_size) % sizeY);
                            v4 = channel.getPixel((x + block_size) % sizeX, (y + block_size) % sizeY);
                            avr = 0.25f*(v1 + v2 + v3 + v4);
                            v5 = avr*(1f + (float)random.NextDouble()*amp - amp_half);
                            channel.putPixel(x + block_size_half, y + block_size_half, v5);
                            y+= block_size;
                        }
                    }
                    // top and bottom edge blocks
                    for (x_block = 1, x = block_size; x_block < (1<<i) - 1; x_block++) {
                        for (y_block = 0; y_block < (1<<i); y_block+= (1<<i) - 1) {
                            y = y_block*block_size;
                            v1 = channel.getPixel(x, y);
                            v2 = channel.getPixel((x + block_size) % sizeX, y);
                            v3 = channel.getPixel(x, (y + block_size) % sizeY);
                            v4 = channel.getPixel((x + block_size) % sizeX, (y + block_size) % sizeY);
                            avr = 0.25f*(v1 + v2 + v3 + v4);
                            v5 = avr*(1f + (float)random.NextDouble()*amp - amp_half);
                            channel.putPixel(x + block_size_half, y + block_size_half, v5);
                        }
                        x+= block_size;
                    }
                }
                // calculate left and bottom edge midpoints
                if (i < 2) {
                    for (x_block = 0, x = 0; x_block < (1<<i); x_block++) {
                        for (y_block = 0, y = 0; y_block < (1<<i); y_block++) {
                            v1 = channel.getPixel(x, y);
                            v5 = channel.getPixel(x + block_size_half, y + block_size_half);
                            v2 = channel.getPixel((x + block_size) % sizeX, y);
                            v3 = channel.getPixel(x, (y + block_size) % sizeY);
                            v6 = channel.getPixel(((x - block_size_half) + sizeX) % sizeX, (y + block_size_half) % sizeY);
                            v7 = channel.getPixel((x + block_size_half) % sizeX, ((y - block_size_half) + sizeY) % sizeY);
                            avr = 0.25f*(v1 + v3 + v5 + v6);
                            v8 = avr*(1f + (float)random.NextDouble()*amp - amp_half);
                            avr = 0.25f*(v1 + v2 + v5 + v7);
                            v9 = avr*(1f + (float)random.NextDouble()*amp - amp_half);
                            channel.putPixel(x, y + block_size_half, v8);
                            channel.putPixel(x + block_size_half, y, v9);
                            y+= block_size;
                        }
                        x+= block_size;
                    }
                } else {
                    // safe blocks
                    for (x_block = 1, x = block_size; x_block < (1<<i) - 1; x_block++) {
                        for (y_block = 1, y = block_size; y_block < (1<<i) - 1; y_block++) {
                            v1 = channel.getPixel(x, y);
                            v5 = channel.getPixel(x + block_size_half, y + block_size_half);
                            v2 = channel.getPixel(x + block_size, y);
                            v3 = channel.getPixel(x, y + block_size);
                            v6 = channel.getPixel(x - block_size_half, y + block_size_half);
                            v7 = channel.getPixel(x + block_size_half, y - block_size_half);
                            avr = 0.25f*(v1 + v3 + v5 + v6);
                            v8 = avr*(1f + (float)random.NextDouble()*amp - amp_half);
                            avr = 0.25f*(v1 + v2 + v5 + v7);
                            v9 = avr*(1f + (float)random.NextDouble()*amp - amp_half);
                            channel.putPixel(x, y + block_size_half, v8);
                            channel.putPixel(x + block_size_half, y, v9);
                            y+= block_size;
                        }
                        x+= block_size;
                    }
                    // left and right edge blocks
                    for (x_block = 0; x_block < (1<<i); x_block+= (1<<i) - 1) {
                        x = x_block*block_size;
                        for (y_block = 0, y = 0; y_block < (1<<i); y_block++) {
                            v1 = channel.getPixel(x, y);
                            v5 = channel.getPixel(x + block_size_half, y + block_size_half);
                            v2 = channel.getPixel((x + block_size) % sizeX, y);
                            v3 = channel.getPixel(x, (y + block_size) % sizeY);
                            v6 = channel.getPixel(((x - block_size_half) + sizeX) % sizeX, (y + block_size_half) % sizeY);
                            v7 = channel.getPixel((x + block_size_half) % sizeX, ((y - block_size_half) + sizeY) % sizeY);
                            avr = 0.25f*(v1 + v3 + v5 + v6);
                            v8 = avr*(1f + (float)random.NextDouble()*amp - amp_half);
                            avr = 0.25f*(v1 + v2 + v5 + v7);
                            v9 = avr*(1f + (float)random.NextDouble()*amp - amp_half);
                            channel.putPixel(x, y + block_size_half, v8);
                            channel.putPixel(x + block_size_half, y, v9);
                            y+= block_size;
                        }
                    }
                    // top and bottom edge blocks
                    for (x_block = 1, x = block_size; x_block < (1<<i) - 1; x_block++) {
                        for (y_block = 0; y_block < (1<<i); y_block+= (1<<i) - 1) {
                            y = y_block*block_size;
                            v1 = channel.getPixel(x, y);
                            v5 = channel.getPixel(x + block_size_half, y + block_size_half);
                            v2 = channel.getPixel((x + block_size) % sizeX, y);
                            v3 = channel.getPixel(x, (y + block_size) % sizeY);
                            v6 = channel.getPixel(((x - block_size_half) + sizeX) % sizeX, (y + block_size_half) % sizeY);
                            v7 = channel.getPixel((x + block_size_half) % sizeX, ((y - block_size_half) + sizeY) % sizeY);
                            avr = 0.25f*(v1 + v3 + v5 + v6);
                            v8 = avr*(1f + (float)random.NextDouble()*amp - amp_half);
                            avr = 0.25f*(v1 + v2 + v5 + v7);
                            v9 = avr*(1f + (float)random.NextDouble()*amp - amp_half);
                            channel.putPixel(x, y + block_size_half, v8);
                            channel.putPixel(x + block_size_half, y, v9);
                        }
                        x+= block_size;
                    }
                }
            }
            float[] mm=channel.findMinMax();
            //Console.WriteLine("Range Mountain->[{0},{1}]",mm[0],mm[1]);
            channel.normalize();
            mm=channel.findMinMax();
            //Console.WriteLine("Range Mountain->[{0},{1}]",mm[0],mm[1]);
        }
Ejemplo n.º 9
0
		public Channel fftInv(Channel magni, Channel phase) {
			if(!(magni.width == magni.height && phase.width == phase.height && magni.width == phase.width))
				throw new Exception("both images must be square and same size");
			int size = magni.width;
			if(!(Utils.isPowerOf2(size)))
				throw new Exception("size must be power of 2");
	
			// convert channels to complex number array
			Channel magnitude = magni.copy().offset(size>>1, size>>1);
			float mag, pha;
			float[] a = new float[size*size*2 + 1];
			int n = 1;
			for (int x = 0; x < size; x++) {
				for (int y = 0; y < size; y++) {
					mag = magnitude.getPixel(x, y);
					pha = phase.getPixel(x, y);
					a[n++] = mag*(float)Math.Cos(pha);
					a[n++] = mag*(float)Math.Sin(pha);
				}
			}
	
			// perform fast fourier transform
			fastFourierTransform(a, size, -1);
	
			// convert complex number array to channel
			n = 1;
			for (int x = 0; x < size; x++) {
				for (int y = 0; y < size; y++) {
					putPixel(x, y, a[n]);
					n += 2;
				}
			}
	
			// return real component channel
			return this;
		}
Ejemplo n.º 10
0
		public Channel place(Channel sprite, Channel alpha, int x_offset, int y_offset) {
			float alpha_val;
			for (int y = y_offset; y < y_offset + sprite.getHeight(); y++) {
				for (int x = x_offset; x < x_offset + sprite.getWidth(); x++) {
					alpha_val = alpha.getPixel(x - x_offset, y - y_offset);
					putPixelWrap(x, y, alpha_val*sprite.getPixelWrap(x - x_offset, y - y_offset) + (1 - alpha_val)*getPixelWrap(x, y));
				}
			}
			return this;
		}
Ejemplo n.º 11
0
		public Channel bump(Channel bumpmap, float lx, float ly, float shadow, float light, float ambient) {
			if(!(bumpmap.getWidth() == width && bumpmap.getHeight() == height))
				throw new Exception("bumpmap does not match channel size");
			Channel channel = new Channel(width, height);
			for (int y = 0; y < height; y++) {
				for (int x = 0; x < width; x++) {
					float nx = bumpmap.getPixelWrap(x + 1, y) - bumpmap.getPixelWrap(x - 1, y);
					float ny = bumpmap.getPixelWrap(x, y + 1) - bumpmap.getPixelWrap(x, y - 1);
					float brightness = nx*lx + ny*ly;
					if (brightness >= 0) {
						channel.putPixelClip(x, y, (getPixel(x, y) + brightness*light)*(bumpmap.getPixel(x, y)*shadow + 1 - shadow));
					} else {
						channel.putPixelClip(x, y, (getPixel(x, y) + brightness*(1 - ambient))*(bumpmap.getPixel(x, y)*shadow + 1 - shadow));
					}
				}
			}
			pixels = channel.getPixels();
			return this;
		}
Ejemplo n.º 12
0
		public Channel smooth(int radius, Channel mask) {
			radius = Math.Max(1, radius);
			Channel filter = new Channel(width, height);
			float factor = 1f/((2*radius + 1)*(2*radius + 1));
			for (int y = 0; y < height; y++) {
				for (int x = 0; x < width; x++) {
					filter.putPixel(x, y, factor*getPixel(x, y));
				}
			}
			for (int x = radius; x < width - radius; x++) {
				int y = radius;
				float sum = 0f;
				for (int i = -radius; i < radius + 1; i++) {
					for (int j = -radius; j < radius + 1; j++) {
						sum += filter.getPixel(x + j, y + i);
					}
				}
				for (y++; y < height - radius; y++) {
					float alpha = mask.getPixel(x, y);
					if (alpha > 0) {
						for (int j = -radius; j < radius + 1; j++) {
							sum -= filter.getPixel(x + j, y - radius - 1);
							sum += filter.getPixel(x + j, y + radius);
						}
						putPixel(x, y, alpha*sum + (1f - alpha)*getPixel(x, y));
					}
				}
			}
			return this;
		}
Ejemplo n.º 13
0
        public static Channel erode5(Channel channel, Channel rain, float erosion_water, float erosion_flow, float evaporation, float water_threshold, float solulibility, int ipr, int iterations)
        {
            Channel w  = new Channel(channel.width, channel.height); // water map
            Channel dw = new Channel(channel.width, channel.height); // delta water map
            Channel s  = new Channel(channel.width, channel.height); // sediment map
            Channel ds = new Channel(channel.width, channel.height); // delta sediment map

            Console.Write("Hydraulic erosion 5: ");

            for (int i = 0; i < iterations; i++) {

                Console.Write(".");

                // save frames
                /*
                if (channel.width > 128 && i%10 == 0) {
                    if (i < 10) {
                        channel.toLayer().saveAsPNG("erosion00" + i);
                    } else if (i < 100) {
                        channel.toLayer().saveAsPNG("erosion0" + i);
                    } else {
                        channel.toLayer().saveAsPNG("erosion" + i);
                    }
                }
                */

                // water is added according to rain map
                if (i%ipr == 0) {
                    w.channelAdd(rain);
                }

                // the presence of water dissolves material
                channel.channelSubtract(w.copy().multiply(erosion_water));
                s.channelAdd(w.copy().multiply(erosion_water));

                // water and sediment are transported
                float h, h1, h2, h3, h4, d1, d2, d3, d4, total_height, total_height_diff, total_height_diff_inv, avr_height, water_amount;
                int cells;
                for (int y = 0; y < channel.height; y++) {
                    for (int x = 0; x < channel.width; x++) {

                        // water transport
                        // calculate total heights and height differences
                        h = channel.getPixel(x, y) + w.getPixel(x, y) + s.getPixel(x, y);

                        h1 = channel.getPixelWrap(x    , y + 1) + w.getPixelWrap(x    , y + 1) + s.getPixelWrap(x    , y + 1);
                        h2 = channel.getPixelWrap(x - 1, y    ) + w.getPixelWrap(x - 1, y    ) + s.getPixelWrap(x - 1, y    );
                        h3 = channel.getPixelWrap(x + 1, y    ) + w.getPixelWrap(x + 1, y    ) + s.getPixelWrap(x + 1, y    );
                        h4 = channel.getPixelWrap(x    , y - 1) + w.getPixelWrap(x    , y - 1) + s.getPixelWrap(x    , y - 1);

                        d1 = h - h1;
                        d2 = h - h2;
                        d3 = h - h3;
                        d4 = h - h4;

                        // calculate amount of water to transport
                        total_height = 0f;
                        total_height_diff = 0f;
                        cells = 1;

                        if (d1 > 0) {
                            total_height_diff+= d1;
                            total_height+= h1;
                            cells++;
                        }
                        if (d2 > 0) {
                            total_height_diff+= d2;
                            total_height+= h2;
                            cells++;
                        }
                        if (d3 > 0) {
                            total_height_diff+= d3;
                            total_height+= h3;
                            cells++;
                        }
                        if (d4 > 0) {
                            total_height_diff+= d4;
                            total_height+= h4;
                            cells++;
                        }

                        if (cells == 1) {
                            continue;
                        }

                        avr_height = total_height/cells;
                        water_amount = Math.Min(w.getPixel(x, y), h - avr_height);
                        dw.putPixel(x, y, dw.getPixel(x, y) - water_amount);
                        total_height_diff_inv = water_amount/total_height_diff;

                        // transport water
                        if (d1 > 0) {
                            dw.putPixelWrap(x, y + 1, dw.getPixelWrap(x, y + 1) + d1*total_height_diff_inv);
                        }
                        if (d2 > 0) {
                            dw.putPixelWrap(x - 1, y, dw.getPixelWrap(x - 1, y) + d2*total_height_diff_inv);
                        }
                        if (d3 > 0) {
                            dw.putPixelWrap(x + 1, y, dw.getPixelWrap(x + 1, y) + d3*total_height_diff_inv);
                        }
                        if (d4 > 0) {
                            dw.putPixelWrap(x, y - 1, dw.getPixelWrap(x, y - 1) + d4*total_height_diff_inv);
                        }

                        // sediment transport
                        /*
                        h = s.getPixel(x, y);

                        h1 = s.getPixelWrap(x    , y + 1);
                        h2 = s.getPixelWrap(x - 1, y    );
                        h3 = s.getPixelWrap(x + 1, y    );
                        h4 = s.getPixelWrap(x    , y - 1);

                        d1 = h - h1;
                        d2 = h - h2;
                        d3 = h - h3;
                        d4 = h - h4;

                        // calculate amount of sediment to transport
                        total_height = 0f;
                        total_height_diff = 0f;
                        cells = 1;

                        if (d1 > 0) {
                            total_height_diff+= d1;
                            total_height+= h1;
                            cells++;
                        }
                        if (d2 > 0) {
                            total_height_diff+= d2;
                            total_height+= h2;
                            cells++;
                        }
                        if (d3 > 0) {
                            total_height_diff+= d3;
                            total_height+= h3;
                            cells++;
                        }
                        if (d4 > 0) {
                            total_height_diff+= d4;
                            total_height+= h4;
                            cells++;
                        }

                        if (cells == 1) {
                            continue;
                        }

                        avr_height = total_height/cells;
                        sediment_amount = Math.Min(s.getPixel(x, y), h - avr_height);
                        ds.putPixel(x, y, ds.getPixel(x, y) - sediment_amount);
                        total_height_diff_inv = sediment_amount/total_height_diff;

                        // transport sediment
                        if (d1 > 0) {
                            ds.putPixelWrap(x, y + 1, ds.getPixelWrap(x, y + 1) + d1*total_height_diff_inv);
                        }
                        if (d2 > 0) {
                            ds.putPixelWrap(x - 1, y, ds.getPixelWrap(x - 1, y) + d2*total_height_diff_inv);
                        }
                        if (d3 > 0) {
                            ds.putPixelWrap(x + 1, y, ds.getPixelWrap(x + 1, y) + d3*total_height_diff_inv);
                        }
                        if (d4 > 0) {
                            ds.putPixelWrap(x, y - 1, ds.getPixelWrap(x, y - 1) + d4*total_height_diff_inv);
                        }
                        */
                    }
                }

                // more sediment is dissolved according to amount of water flow
                /*
                channel.channelSubtract(dw.copy().fill(0f, Float.MIN_VALUE, 0f).multiply(erosion_flow));
                s.channelAdd(dw.copy().fill(0f, Float.MIN_VALUE, 0f).multiply(erosion_flow));
                */

                // apply water and sediment delta maps
                w.channelAdd(dw);
                //w.fill(0f, Float.MIN_VALUE, water_threshold); // remove water below threshold amount
                s.channelAdd(ds);
                dw.fill(0f);
                ds.fill(0f);

                // water evaporates
                w.multiply(evaporation);

                // sediment is deposited
                for (int y = 0; y < channel.height; y++) {
                    for (int x = 0; x < channel.width; x++) {
                        float deposition = s.getPixel(x, y) - w.getPixel(x, y)*solulibility;
                        if (deposition > 0) {
                            s.putPixel(x, y, s.getPixel(x, y) - deposition);
                            channel.putPixel(x, y, channel.getPixel(x, y) + deposition);
                        }
                    }
                }
            }

            Console.WriteLine("DONE");

            return channel;
        }
Ejemplo n.º 14
0
		public Channel scaleDouble() {
			if(!(width == height)) throw new Exception("square images only");
	
			// calculate filter
			Channel filter = new Channel(width<<1, height<<1);
			for (int y = 0; y < height; y++) {
				int y_shift = y<<1;
				for (int x = 0; x < width; x++) {
					int x_shift = x<<1;
					float value = 0.25f*getPixel(x, y);
					filter.putPixel(x_shift, y_shift, value);
					filter.putPixel(x_shift + 1, y_shift, value);
					filter.putPixel(x_shift, y_shift + 1, value);
					filter.putPixel(x_shift + 1, y_shift + 1, value);
				}
			}
	
			// draw image
			Channel channel = new Channel(width<<1, height<<1);
			for (int y = 1; y < (height<<1) - 1; y++) {
				for (int x = 1; x < (width<<1) - 1; x++) {
					channel.putPixel(x, y, filter.getPixel(x - 1, y) + filter.getPixel(x + 1, y) + filter.getPixel(x, y - 1) + filter.getPixel(x, y + 1));
				}
			}
	
			// fix edges
			int max = (width<<1) - 1;
			for (int i = 0; i < max; i++) {
				channel.putPixel(0, i, filter.getPixelWrap(-1, i) + filter.getPixelWrap(1, i) + filter.getPixelWrap(0, i - 1) + filter.getPixelWrap(0, i + 1));
				channel.putPixel(i, 0, filter.getPixelWrap(i, -1) + filter.getPixelWrap(i, 1) + filter.getPixelWrap(i - 1, 0) + filter.getPixelWrap(i + 1, 0));
				channel.putPixel(max, i, filter.getPixelWrap(max - 1, i) + filter.getPixelWrap(max + 1, i) + filter.getPixelWrap(max, i - 1) + filter.getPixelWrap(max, i + 1));
				channel.putPixel(i, max, filter.getPixelWrap(i, max - 1) + filter.getPixelWrap(i, max + 1) + filter.getPixelWrap(i - 1, max) + filter.getPixelWrap(i + 1, max));
			}
			pixels = channel.getPixels();
			width = width<<1;
			height = height<<1;
			return this;
		}
Ejemplo n.º 15
0
		public Channel channelAdd(Channel channel) {
			for (int y = 0; y < height; y++) {
				for (int x = 0; x < width; x++) {
					try
					{
						putPixelClip(x, y, getPixel(x, y) + channel.getPixel(x, y));
					} catch(Exception) {
						putPixelClip(x,y,0f);
						Console.WriteLine("Failed to get pixel ("+x.ToString()+","+y.ToString()+").");
					}
				}
			}
			return this;
		}
Ejemplo n.º 16
0
		public Channel perturb(Channel perturb, float magnitude) {
			Channel channel = new Channel(width, height);
			for (int y = 0; y < height; y++) {
				for (int x = 0; x < width; x++) {
					float perturbation = magnitude*(perturb.getPixel(x, y) - 0.5f);
					float x_coord = x + width*perturbation;
					int x_coord_lo = (int)x_coord;
					int x_coord_hi = x_coord_lo + 1;
					float x_frac = x_coord - x_coord_lo;
					float y_coord = y + height*perturbation;
					int y_coord_lo = (int)y_coord;
					int y_coord_hi = y_coord_lo + 1;
					float y_frac = y_coord - y_coord_lo;
					float val1 = Tools.interpolateLinear(getPixelWrap(x_coord_lo, y_coord_lo), getPixelWrap(x_coord_hi, y_coord_lo), x_frac);
					float val2 = Tools.interpolateLinear(getPixelWrap(x_coord_lo, y_coord_hi), getPixelWrap(x_coord_hi, y_coord_hi), x_frac);
					channel.putPixel(x, y, Tools.interpolateLinear(val1, val2, y_frac));
				}
			}
			pixels = channel.getPixels();
			return this;
		}
Ejemplo n.º 17
0
		public Channel channelSubtractNoClip(Channel channel) {
			for (int y = 0; y < height; y++) {
				for (int x = 0; x < width; x++) {
					putPixel(x, y, getPixel(x, y) - channel.getPixel(x, y));
				}
			}
			return this;
		}
Ejemplo n.º 18
0
		public Midpoint(int size, int base_freq, float pers, long seed) {
			if(!Utils.isPowerOf2(size))
				throw new Exception("size must be power of 2");
			int iterations = Utils.powerOf2Log2(size);
			base_freq = Math.Max(base_freq, 0);
			base_freq = Math.Min(base_freq, iterations);
			random = new Random((int)seed);
			channel = new Channel(size, size);
	
			
			int x_block, y_block, x, y;
			
			if (base_freq > 0) {
				int block_size = size>>base_freq;
				for (x_block = 0; x_block < (1<<base_freq); x_block++) {
					for (y_block = 0; y_block < (1<<base_freq); y_block++) {
						x = x_block*block_size;
						y = y_block*block_size;
						channel.putPixel(x, y, (float)random.NextDouble());
					}
				}
			}
	
			float v1, v2, v3, v4, v5, v6, v7, v8, v9;
	
			for (int i = base_freq; i < iterations; i++) {
				int block_size = size>>i;
				int block_size_half = size>>(i + 1);
				float amp = (float)Math.Pow(pers, i - base_freq);
				float amp_half = 0.5f*amp;
				// calculate center midpoints
				if (i < 2) {
					for (x_block = 0, x = 0; x_block < (1<<i); x_block++) {
						for (y_block = 0, y = 0; y_block < (1<<i); y_block++) {
							v1 = channel.getPixel(x, y);
							v2 = channel.getPixel((x + block_size) % size, y);
							v3 = channel.getPixel(x, (y + block_size) % size);
							v4 = channel.getPixel((x + block_size) % size, (y + block_size) % size);
							v5 = 0.25f*(v1 + v2 + v3 + v4) + (float)random.NextDouble()*amp - amp_half;
							channel.putPixel(x + block_size_half, y + block_size_half, v5);
							y+= block_size;
						}
						x+= block_size;
					}
				} else {
					// safe blocks
					for (x_block = 1, x = block_size; x_block < (1<<i) - 1; x_block++) {
						for (y_block = 1, y = block_size; y_block < (1<<i) - 1; y_block++) {
							v1 = channel.getPixel(x, y);
							v2 = channel.getPixel(x + block_size, y);
							v3 = channel.getPixel(x, y + block_size);
							v4 = channel.getPixel(x + block_size, y + block_size);
							v5 = 0.25f*(v1 + v2 + v3 + v4) + (float)random.NextDouble()*amp - amp_half;
							channel.putPixel(x + block_size_half, y + block_size_half, v5);
							y+= block_size;
						}
						x+= block_size;
					}
					// left and right edge blocks
					for (x_block = 0; x_block < (1<<i); x_block+= (1<<i) - 1) {
						x = x_block*block_size;
						for (y_block = 0, y = 0; y_block < (1<<i); y_block++) {
							v1 = channel.getPixel(x, y);
							v2 = channel.getPixel((x + block_size) % size, y);
							v3 = channel.getPixel(x, (y + block_size) % size);
							v4 = channel.getPixel((x + block_size) % size, (y + block_size) % size);
							v5 = 0.25f*(v1 + v2 + v3 + v4) + (float)random.NextDouble()*amp - amp_half;
							channel.putPixel(x + block_size_half, y + block_size_half, v5);
							y+= block_size;
						}
					}
					// top and bottom edge blocks
					for (x_block = 1, x = block_size; x_block < (1<<i) - 1; x_block++) {
						for (y_block = 0; y_block < (1<<i); y_block+= (1<<i) - 1) {
							y = y_block*block_size;
							v1 = channel.getPixel(x, y);
							v2 = channel.getPixel((x + block_size) % size, y);
							v3 = channel.getPixel(x, (y + block_size) % size);
							v4 = channel.getPixel((x + block_size) % size, (y + block_size) % size);
							v5 = 0.25f*(v1 + v2 + v3 + v4) + (float)random.NextDouble()*amp - amp_half;
							channel.putPixel(x + block_size_half, y + block_size_half, v5);
						}
						x+= block_size;
					}
				}
				// calculate left and bottom edge midpoints
				if (i < 2) {
					for (x_block = 0, x = 0; x_block < (1<<i); x_block++) {
						for (y_block = 0, y = 0; y_block < (1<<i); y_block++) {
							v1 = channel.getPixel(x, y);
							v5 = channel.getPixel(x + block_size_half, y + block_size_half);
							v2 = channel.getPixel((x + block_size) % size, y);
							v3 = channel.getPixel(x, (y + block_size) % size);
							v6 = channel.getPixel(((x - block_size_half) + size) % size, (y + block_size_half) % size);
							v7 = channel.getPixel((x + block_size_half) % size, ((y - block_size_half) + size) % size);
							v8 = 0.25f*(v1 + v3 + v5 + v6) + (float)random.NextDouble()*amp - amp_half;
							v9 = 0.25f*(v1 + v2 + v5 + v7) + (float)random.NextDouble()*amp - amp_half;
							channel.putPixel(x, y + block_size_half, v8);
							channel.putPixel(x + block_size_half, y, v9);
							y+= block_size;
						}
						x+= block_size;
					}
				} else {
					// safe blocks
					for (x_block = 1, x = block_size; x_block < (1<<i) - 1; x_block++) {
						for (y_block = 1, y = block_size; y_block < (1<<i) - 1; y_block++) {
							v1 = channel.getPixel(x, y);
							v5 = channel.getPixel(x + block_size_half, y + block_size_half);
							v2 = channel.getPixel(x + block_size, y);
							v3 = channel.getPixel(x, y + block_size);
							v6 = channel.getPixel(x - block_size_half, y + block_size_half);
							v7 = channel.getPixel(x + block_size_half, y - block_size_half);
							v8 = 0.25f*(v1 + v3 + v5 + v6) + (float)random.NextDouble()*amp - amp_half;
							v9 = 0.25f*(v1 + v2 + v5 + v7) + (float)random.NextDouble()*amp - amp_half;
							channel.putPixel(x, y + block_size_half, v8);
							channel.putPixel(x + block_size_half, y, v9);
							y+= block_size;
						}
						x+= block_size;
					}
					// left and right edge blocks
					for (x_block = 0; x_block < (1<<i); x_block+= (1<<i) - 1) {
						x = x_block*block_size;
						for (y_block = 0, y = 0; y_block < (1<<i); y_block++) {
							v1 = channel.getPixel(x, y);
							v5 = channel.getPixel(x + block_size_half, y + block_size_half);
							v2 = channel.getPixel((x + block_size) % size, y);
							v3 = channel.getPixel(x, (y + block_size) % size);
							v6 = channel.getPixel(((x - block_size_half) + size) % size, (y + block_size_half) % size);
							v7 = channel.getPixel((x + block_size_half) % size, ((y - block_size_half) + size) % size);
							v8 = 0.25f*(v1 + v3 + v5 + v6) + (float)random.NextDouble()*amp - amp_half;
							v9 = 0.25f*(v1 + v2 + v5 + v7) + (float)random.NextDouble()*amp - amp_half;
							channel.putPixel(x, y + block_size_half, v8);
							channel.putPixel(x + block_size_half, y, v9);
							y+= block_size;
						}
					}
					// top and bottom edge blocks
					for (x_block = 1, x = block_size; x_block < (1<<i) - 1; x_block++) {
						for (y_block = 0; y_block < (1<<i); y_block+= (1<<i) - 1) {
							y = y_block*block_size;
							v1 = channel.getPixel(x, y);
							v5 = channel.getPixel(x + block_size_half, y + block_size_half);
							v2 = channel.getPixel((x + block_size) % size, y);
							v3 = channel.getPixel(x, (y + block_size) % size);
							v6 = channel.getPixel(((x - block_size_half) + size) % size, (y + block_size_half) % size);
							v7 = channel.getPixel((x + block_size_half) % size, ((y - block_size_half) + size) % size);
							v8 = 0.25f*(v1 + v3 + v5 + v6) + (float)random.NextDouble()*amp - amp_half;
							v9 = 0.25f*(v1 + v2 + v5 + v7) + (float)random.NextDouble()*amp - amp_half;
							channel.putPixel(x, y + block_size_half, v8);
							channel.putPixel(x + block_size_half, y, v9);
						}
						x+= block_size;
					}
				}
			}
			channel.normalize();
		}
Ejemplo n.º 19
0
		public Channel channelAverage(Channel channel) {
			for (int y = 0; y < height; y++) {
				for (int x = 0; x < width; x++) {
					putPixel(x, y, (getPixel(x, y) + channel.getPixel(x, y))/2f);
				}
			}
			return this;
		}
Ejemplo n.º 20
0
 public Layer bumpSpecular(Channel bumpmap, float lx, float ly, float lz, float shadow, float light_r, float light_g, float light_b, int specular)
 {
     if(!(bumpmap.getWidth() == width && bumpmap.getHeight() == height))
         throw new Exception("bumpmap size does not match layer size");
     float lnorm = (float)Math.Sqrt(lx*lx + ly*ly + lz*lz);
     float nz = 4*(1f/Math.Min(width, height));
     float nzlz = nz*lz;
     float nz2 = nz*nz;
     int power = 2<<specular;
     for (int y = 0; y < height; y++) {
         for (int x = 0; x < width; x++) {
             float nx = bumpmap.getPixelWrap(x + 1, y) - bumpmap.getPixelWrap(x - 1, y);
             float ny = bumpmap.getPixelWrap(x, y + 1) - bumpmap.getPixelWrap(x, y - 1);
             float brightness = nx*lx + ny*ly;
             float costheta = (brightness + nzlz)/((float)Math.Sqrt(nx*nx + ny*ny + nz2)*lnorm);
             float highlight;
             if (costheta > 0) {
                 highlight = (float)Math.Pow(costheta, power);
             } else {
                 highlight = 0;
             }
             putPixelClip(x, y,
                 (r.getPixel(x, y) + highlight*light_r)*(bumpmap.getPixel(x, y)*shadow + 1 - shadow),
                 (g.getPixel(x, y) + highlight*light_g)*(bumpmap.getPixel(x, y)*shadow + 1 - shadow),
                 (b.getPixel(x, y) + highlight*light_b)*(bumpmap.getPixel(x, y)*shadow + 1 - shadow));
         }
     }
     return this;
 }
Ejemplo n.º 21
0
        public static Channel erode3(Channel channel, Channel rain_map, float vaporization, int rain_freq, int iterations)
        {
            Channel vapor_map = rain_map.copy().multiply(0.5f);
            Channel height_map_diff = new Channel(channel.width, channel.height).fill(0f);
            Channel water_map = new Channel(channel.width, channel.height).fill(0f);
            Channel water_map_diff = new Channel(channel.width, channel.height).fill(0f);
            Channel sediment_map = new Channel(channel.width, channel.height).fill(0f);
            Channel sediment_map_diff = new Channel(channel.width, channel.height).fill(0f);

            Console.Write("Hydraulic erosion 3: ");

            for (int i = 0; i < iterations; i++) {

                Console.Write(".");

                // save frames
                /*
                if (channel.width > 128 && i%8 == 0) {
                    if (i < 10) {
                        channel.toLayer().saveAsPNG("erosion00" + i);
                    } else if (i < 100) {
                        channel.toLayer().saveAsPNG("erosion0" + i);
                    } else {
                        channel.toLayer().saveAsPNG("erosion" + i);
                    }
                }
                */

                // rain
                if (i%rain_freq == 0) {
                    water_map.channelAdd(rain_map);
                }

                // water and sediment transport
                for (int y = 1; y < channel.height - 1; y++) {
                    for (int x = 1; x < channel.width - 1; x++) {

                        // calculate total heights and height differences
                        float h = channel.getPixel(x, y) + water_map.getPixel(x, y);

                        float h1 = channel.getPixel(x, y + 1) + water_map.getPixel(x, y + 1) + sediment_map.getPixel(x, y + 1);
                        float h2 = channel.getPixel(x - 1, y) + water_map.getPixel(x - 1, y) + sediment_map.getPixel(x - 1, y);
                        float h3 = channel.getPixel(x + 1, y) + water_map.getPixel(x + 1, y) + sediment_map.getPixel(x + 1, y);
                        float h4 = channel.getPixel(x, y - 1) + water_map.getPixel(x, y - 1) + sediment_map.getPixel(x, y - 1);

                        float d1 = h - h1;
                        float d2 = h - h2;
                        float d3 = h - h3;
                        float d4 = h - h4;

                        // calculate amount of water and sediment to transport
                        float total_height = 0;
                        float total_height_diff = 0;
                        int cells = 1;

                        if (d1 > 0) {
                            total_height_diff+= d1;
                            total_height+= h1;
                            cells++;
                        }
                        if (d2 > 0) {
                            total_height_diff+= d2;
                            total_height+= h2;
                            cells++;
                        }
                        if (d3 > 0) {
                            total_height_diff+= d3;
                            total_height+= h3;
                            cells++;
                        }
                        if (d4 > 0) {
                            total_height_diff+= d4;
                            total_height+= h4;
                            cells++;
                        }

                        if (cells == 1) {
                            continue;
                        }

                        float avr_height = total_height/cells;

                        float water_amount = Math.Min(water_map.getPixel(x, y), h - avr_height);
                        water_map_diff.putPixel(x, y, water_map_diff.getPixel(x, y) - water_amount);
                        float water_inv = water_amount/total_height_diff;

                        float sediment_amount = sediment_map.getPixel(x, y);
                        sediment_map_diff.putPixel(x, y, sediment_map_diff.getPixel(x, y) - sediment_amount);
                        float sediment_inv = sediment_amount/total_height_diff;

                        float dissolve;

                        // transport water and sediment and dissolve more material
                        if (d1 > 0) {
                            water_map_diff.putPixel(x, y + 1, water_map_diff.getPixel(x, y + 1) + d1*water_inv);
                            dissolve = 10f*d1*water_amount;
                            sediment_map_diff.putPixel(x, y + 1, sediment_map_diff.getPixel(x, y + 1) + d1*sediment_inv + dissolve);
                            height_map_diff.putPixel(x, y + 1, height_map_diff.getPixel(x, y + 1) - dissolve);
                        }
                        if (d2 > 0) {
                            water_map_diff.putPixel(x - 1, y, water_map_diff.getPixel(x - 1, y) + d2*water_inv);
                            dissolve = 10f*d2*water_amount;
                            sediment_map_diff.putPixel(x - 1, y, sediment_map_diff.getPixel(x - 1, y) + d2*sediment_inv + dissolve);
                            height_map_diff.putPixel(x - 1, y, height_map_diff.getPixel(x - 1, y) - dissolve);
                        }
                        if (d3 > 0) {
                            water_map_diff.putPixel(x + 1, y, water_map_diff.getPixel(x + 1, y) + d3*water_inv);
                            dissolve = 10f*d3*water_amount;
                            sediment_map_diff.putPixel(x + 1, y, sediment_map_diff.getPixel(x + 1, y) + d3*sediment_inv + dissolve);
                            height_map_diff.putPixel(x + 1, y, height_map_diff.getPixel(x + 1, y) - dissolve);
                        }
                        if (d4 > 0) {
                            water_map_diff.putPixel(x, y - 1, water_map_diff.getPixel(x, y - 1) + d4*water_inv);
                            dissolve = 10f*d4*water_amount;
                            sediment_map_diff.putPixel(x, y - 1, sediment_map_diff.getPixel(x, y - 1) + d4*sediment_inv + dissolve);
                            height_map_diff.putPixel(x, y - 1, height_map_diff.getPixel(x, y - 1) - dissolve);
                        }
                    }
                }

                // apply changes to water map
                water_map.channelAddNoClip(water_map_diff);

                // apply changes to sediment map
                sediment_map.channelAddNoClip(sediment_map_diff);

                // apply changes to height map
                channel.channelAddNoClip(height_map_diff);

                // water vaporization
                water_map.addClip(-vaporization);

                // sedimentation
                sediment_map_diff = sediment_map.copy().channelSubtract(water_map);
                sediment_map.channelSubtract(sediment_map_diff);
                channel.channelAddNoClip(sediment_map_diff);

                // clear diff maps
                water_map_diff.fill(0f);
                height_map_diff.fill(0f);
                sediment_map_diff.fill(0f);
            }

            // force evaporation of remaining water
            //channel.channelAdd(water_map.multiply(0.5f));

            Console.WriteLine("DONE");

            return channel;
        }