# Wolken Bild/Grafik vom Programm erstellen lassen



## Sphinx2k (21. Mrz 2012)

Hallo,
Ich möchte eine 2D Wolke mit meinem Programm erstellen wie geht das?

Ok etwas genauer beschrieben. Ich möchte zur Laufzeit von meinem Programm einen Hintergrund erstellen lassen der bunte Wolken enthält. 
Sagen wir so etwas hier Directupload.net - Dj5bswysc.png
Das ganze soll auch nicht die ganze Fläche ausfüllen sondern ich möchte die Bereiche wo diese Wolken sind begrenzen. 
Vermute mal es gibt für so etwas passende Mathematische Konstrukte mit einem Tollen Namen.

Ich hab leider keine Idee unter welchem Stichpunkten ich zu diesem Thema etwas in einer Suchmaschine finden könnte. Also alleine das wäre mir schon eine große Hilfe.


----------



## Marco13 (21. Mrz 2012)

Könnte grob (!) in Richtung Plasma (Demoszene) ? Wikipedia gehen...


----------



## Sphinx2k (21. Mrz 2012)

Ja das könnte hinkommen. Eine gerade noch von mir entdeckte Möglichkeit scheint "Perlin Noise" zu sein.


----------



## Marco13 (21. Mrz 2012)

Ja, ... unterbewußt hatte ich das auch im Kopf... (irgendwas mit "P" ) ... eben das, wo man quasi eine "zufällige Landschaft" aus "Höhenwerten" (=Farben) baut, indem man die Landschaft rekursiv immer weiter unterteilt...


----------



## Sphinx2k (21. Mrz 2012)

Sehr gut beschriebenes Tutorial dazu war hier das.
How to Use Perlin Noise in Your Games » devmag.org.za

Denke ich bin damit erst mal zufrieden. Danke.


----------



## Fu3L (21. Mrz 2012)

Danke, dass du deinen Fund mit uns teilst. Ich nutze Perlin Noise, um Terrain zur Laufzeit zu generieren, will aber auch den Himmel damit färben, wenn zB Magie gewirkt wird. Bin also auch an dem was in dem, Artikel beschrieben wird, interessiert.


----------



## Marco13 (21. Mrz 2012)

Hmja, so eine angefangene Implementierung vom Perlin lag bei mir hier auch schon ewig rum. Damals hatte ich versucht, den Pseudocode von Perlin Noise direkt zu übernehmen, aber da kam nur murks raus. Hab' jetzt nochmal eins in Anlehung an The Perlin noise math FAQ implementiert, vielleicht kann's ja jemand brauchen:


```
// Marco13 for [url]http://www.java-forum.org/spiele-multimedia-programmierung/133653-wolken-bild-grafik-programm-erstellen-lassen.html#post878969[/url]

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public class PerlinNoiseTest
{
    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                createAndShowGUI();
            }
        });
    }
    
    private static void createAndShowGUI()
    {
        JFrame f = new JFrame();        
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        int sizeX = 500;
        int sizeY = 500;
        BufferedImage image = new BufferedImage(sizeX,sizeY,BufferedImage.TYPE_INT_ARGB);
        
        Noise noise = new MultiLevelPerlinNoise(6);
        int colorMap[] = createColorMap(64, Color.RED, Color.GREEN, Color.BLUE);
        
        fillImage(image, noise, colorMap);
        
        f.getContentPane().setLayout(new BorderLayout());
        f.getContentPane().add(new JLabel(new ImageIcon(image)));
        f.pack();
        f.setVisible(true);
    }
    
    private static void fillImage(BufferedImage image, Noise noise, int colorMap[])
    {
        int min = Integer.MAX_VALUE;
        int max = -Integer.MAX_VALUE;
        int resolution = Short.MAX_VALUE;
        int w = image.getWidth();
        int h = image.getHeight();
        for (int x=0; x<w; x++)
        {
            for (int y=0; y<h; y++)
            {
                double value = noise.get((double)x/w,(double)y/h);
                int v = (int)(value * resolution);
                min = Math.min(min, v);
                max = Math.max(max, v);
                image.setRGB(x,y,v);
            }
        }
        for (int i=0; i<w; i++)
        {
            for (int j=0; j<h; j++)
            {
                int v = image.getRGB(i, j);
                double value = (double)(v-min) / (max-min);
                int index = (int)(value * (colorMap.length-1));
                image.setRGB(i,j,colorMap[index]);
            }
        }
    }
    
    private static int[] createColorMap(int stepSize, Color ... colors)
    {
        int colorMap[] = new int[stepSize*(colors.length-1)];
        int index = 0;
        for (int i=0; i<colors.length-1; i++)
        {
            Color c0 = colors[i];
            int r0 = c0.getRed();
            int g0 = c0.getGreen();
            int b0 = c0.getBlue();

            Color c1 = colors[i+1];
            int r1 = c1.getRed();
            int g1 = c1.getGreen();
            int b1 = c1.getBlue();
            
            int dr = r1-r0;
            int dg = g1-g0;
            int db = b1-b0;

            for (int j=0; j<stepSize; j++)
            {
                float alpha = (float)j / (stepSize-1);
                int r = (int)(r0 + alpha * dr);
                int g = (int)(g0 + alpha * dg);
                int b = (int)(b0 + alpha * db);
                int rgb = 
                    0xFF000000 |
                    (r << 16) |
                    (g <<  8) |
                    (b <<  0);
                colorMap[index++] = rgb;
            }
        }
        return colorMap;
    }
}




interface Noise
{
    double get(double x, double y);
}

class MultiLevelPerlinNoise implements Noise
{
    private final List<Noise> noises;
    
    public MultiLevelPerlinNoise(int levels)
    {
        noises = new ArrayList<Noise>();
        for (int i=0; i<levels; i++)
        {
            int size = 2*(1<<i);
            noises.add(new PerlinNoise(size, size));
        }
    }
    
    public double get(double x, double y)
    {
        double z = 0;
        double amplitude = 1;
        double persistance = 0.5;
        double totalAmplitude = 0;
        for (Noise noise : noises)
        {
            amplitude *= persistance;
            totalAmplitude += amplitude;
            z += amplitude * noise.get(x, y);
        }
        z /= totalAmplitude;
        return z;
    }
}

// Based on [url=http://webstaff.itn.liu.se/~stegu/TNM022-2005/perlinnoiselinks/perlin-noise-math-faq.html]The Perlin noise math FAQ[/url]
class PerlinNoise implements Noise
{
    private static final double INV_SQRT2 = 1.0/Math.sqrt(2);
    private static final Random random = new Random();
    private final int gridSizeX;
    private final int gridSizeY;
    private final Vec g[][];

    public PerlinNoise(int gridSizeX, int gridSizeY)
    {
        this.gridSizeX = gridSizeX;
        this.gridSizeY = gridSizeY;
        g = new Vec[gridSizeX][gridSizeY];
        for (int x=0; x<gridSizeX; x++)
        {
            for (int y=0; y<gridSizeY; y++)
            {
                g[x][y] = new Vec();
            }
        }
    }
    
    private static class Vec
    {
        double x;
        double y;
        
        private Vec()
        {
            x = -1 + 2 * random.nextDouble(); 
            y = -1 + 2 * random.nextDouble(); 
            double s = 1.0 / Math.sqrt(x*x+y*y);
            x *= s;
            y *= s;
        }
    }
    
    @Override
    public double get(double rx, double ry)
    {
        double x = rx * (gridSizeX-1);
        double y = ry * (gridSizeY-1);
        int x0 = (int)x;
        int y0 = (int)y;
        int x1 = x0+1;
        int y1 = y0+1;
        double dx0 = x-x0;
        double dy0 = y-y0;
        double dx1 = x-x1;
        double dy1 = y-y1;
        double d00 = g[x0][y0].x * dx0 + g[x0][y0].y * dy0; 
        double d10 = g[x1][y0].x * dx1 + g[x1][y0].y * dy0; 
        double d01 = g[x0][y1].x * dx0 + g[x0][y1].y * dy1; 
        double d11 = g[x1][y1].x * dx1 + g[x1][y1].y * dy1;
        double ix = curve(dx0);
        double a = d00 + ix*(d10-d00);
        double b = d01 + ix*(d11-d01);
        double iy = curve(dy0);
        double z = a + iy*(b-a);
        return 0.5 + z * INV_SQRT2;
    }
    
    private static double curve(double t) 
    {
        return t * t * (3.0 - 2.0 * t);
    }
}
```


----------



## Fu3L (21. Mrz 2012)

Auch danke dafür. Alternative Implementierungen zu sehen, kann bestimmt nicht schaden 

PS: Bist du dir eigentlich bewusst, dass ich einen eigenes Package mit Codesnippets von dir habe?^^


----------



## Apo (22. Mrz 2012)

Auch von mir: Vielen Dank. Habe es mir auch gleich mal gesichert und werde damit etwas rumspielen!


----------



## Marco13 (22. Mrz 2012)

Fu3L hat gesagt.:


> Auch danke dafür. Alternative Implementierungen zu sehen, kann bestimmt nicht schaden



Der wichtigste Unterschied zwischen dem ursprünglich verlinkten und dieser Implementierung ist wohl, dass beim ersten diese ganzen Arrays einmal berechnet und dann zu einen gemischten Perlin-Array kombiniert werden. Mit dem angedeuteten "Noise"-Interface wird hier jede einzelne Frequenz als eine Noise-Funktion aufgefaßt, und erst beim "get" werden die Werte kombiniert (diese Parameter, "amplitude" und "persistence", könnte man damit z.B. leichter nachträglich ändern um die Auswirkungen zu sehen). Natürlich ist der Zugriff damit kein einfacher Array-Lookup mehr, aber ich denke, dass das so interessantere Möglichkeiten bietet und flexibler ist: Eine Funktion, die ein get(x,y) anbietet in einen Array mit festgelegter Größe zu dumpen ist einfach - umgekehrt geht das nicht 



Fu3L hat gesagt.:


> PS: Bist du dir eigentlich bewusst, dass ich einen eigenes Package mit Codesnippets von dir habe?^^



Eigentlich wollte ich schon immer mal meine Snippet-Sammlung online stellen (glaub' mir: Es ist viel, viel, viel mehr als das, was hier im Forum landet  ) aber ohne Suchfunktion und so bringt das nicht viel - vom Zeitaufwand, das ganze postbar glattzuziehen mal ganz abgesehen ....


----------



## Guest2 (22. Mrz 2012)

Moin,

[ot]



Marco13 hat gesagt.:


> Eigentlich wollte ich schon immer mal meine Snippet-Sammlung online stellen (glaub' mir: Es ist viel, viel, viel mehr als das, was hier im Forum landet  ) aber ohne Suchfunktion und so bringt das nicht viel - vom Zeitaufwand, das ganze postbar glattzuziehen mal ganz abgesehen ....



Hast Du Dir mal https://gist.github.com/ angesehen?

Das ist für Snippets gemacht. Neben allen git features (versionieren, forken, usw.) kann man auch suchen, kommentieren, ...  Über den Eclipse Mylyn connector lässt sich das auch in die IDE einbinden.



> Gists are also supported, you can now highlight text in the editor or select a file from the explorer and run Create Gist from the context menu. A Gist will be created in the background and a notification popup will display after it has been created with a link to the newly created Gist. [..]
> You can also browse and search for Gists from within Eclipse, open a Gist's files in the Eclipse editor, and add or update the contents of a Gist. If you want to work with a Gist as a Git repository just click the Clone button from the toolbar and the Gist will be cloned locally and imported as an Eclipse project.



(Allerdings habe ich bisher damit auch nur rumgespielt...)

[/ot]

Viele Grüße,
Fancy


----------



## Marco13 (22. Mrz 2012)

Sieht cool aus, werd' ich mir mal ansehen!


----------

