12/22/2015

Gravitational Field

Und noch ein neues Experiment. Wieder Partikel. Wieder 3D.
Dieses Mal, wie der Name schon verrät, geht es um Schwerkraft, oder genauer gesagt, um ein „Gravitational Field“.
In diesem Experiment stehen die Pixel, bzw. Partikel  stellvertretend für Sterne. Jeder Stern hat eine Masse. Initial wird jedem Stern per Zufall eine bestimmte Masse zugewiesen. Startet man die Simulation, kann man beobachten, wie sich die Sterne gegenseitig in ihrer Bewegung, gesteuert durch Massen und Kräfte, beeinflussen. Es entsteht eine Art von Galaxie wenn man das vereinfacht ausdrückt. Und, es sieht auch so aus. Um die „Flugbahnen“ der Sterne besser nachvollziehen zu können hinterlassen diese Spuren. Auf diese Weise entsteht eine interessante Simulation, die man durch diverse Parameter beeinflussen kann. 


Die Mathe dahinter ist schon ein Stück weit komplizierter. Aber zum Glück muss man das Rad ja nicht immer neu erfinden. Auf CodePen finden sich viele schöne Experimente und Spielereien. Und speziell dieses eine Experiment hier: „Simulating gravity between many entities“ hat mir richtig gut weitergeholfen. Natürlich musste ich das Ganze noch von 2D auf 3D übetragen und ein paar andere Dinge anpassen, aber im Großen und Ganzen war dieses Beispiel der Schlüssel zum Erfolg. Ein Dank also an dieser Stelle an den Autor „ysor“.


Zurück zur Simulation. Über „Open Controls“ könnt ihr, wie immer eigentlich, diverse Parameter verändern und somit Einfluss auf die Simulation nehmen. Zunächst einmal müsst ihr die Simulation starten. Klickt dazu einfach auf das Experiment. Schon geht’s los. Ein erneuter Klick stoppt die Simulation usw. usw. Mit der Maus könnt ihr die Szene wie gewohnt frei drehen.
Der „Restart“ Button ist wohl ziemlich selbsterklärend. Speziell die beiden Buttons darunter, „Star Amount“ und „Path Length“ sind mit etwas Vorsicht zu genießen. Erhöht man die Werte zu drastisch, könnte das euren Rechner in die Knie zwingen.  „Star Amount“ bestimmt die Anzahl an Sternen und mit „Path Length“ legt ihr fest, wie lange jeweils die Spur eines Sterns sein soll. Mit „Gravity“ könnt ihr die globale Schwerkraft beeinflussen und mit „Speed“ die Geschwindigkeit mit der die Simulation abläuft. „Mass Min“ und „Mass Max“ sind die Werte zwischen denen zu Beginn die Massen für die einzelnen Sterne bestimmt werden. Erklären ist an dieser Stelle schön und gut. Aber Ausprobieren ist mit Sicherheit interessanter.


Besucher, die mit mobilen Geräten unterwegs sind, die sollten die Simulation am besten in einem neuen Fenster öffnen. 


12/18/2015

Neural Network V2

Dieses künstliche neuronale Netz ist eine Weiterentwicklung des „Neural Network“.
Auch hierbei handelt es sich natürlich nicht um ein echtes neuronales Netz, aber die Simulation ist jetzt ein Stück weit realistischer, oder zumindest näher an einem neuronalen Netz, als das erste Experiment. 


Vom Verhalten her haben sich die Neuronen kaum verändert. Lediglich die Geschwindigkeit, mit der sich die Neuronen bewegen, kann jetzt bei den Einstellungen geändert werden.
Das wirklich Neue aber ist die Datenübertragung zwischen den einzelnen Neuronen. Daten in Form von Farbwerten, die so auch in der Simulation dargestellt werden. 


Jedes Neuron kann einen von 10 Farbwerten annehmen. Nähern sich zwei Neuronen so nah an, dass die Distanz zwischen ihnen den Grenzwert (Kann in den Einstellungen verändert werden) unterschreitet, wird nicht einfach  nur eine Linie sichtbar, sondern es findet auch eine primitive Kommunikation zwischen den beiden Neuronen statt. Und genau das soll durch die Verbindungslinie veranschaulicht werden soll. Das Neuron schaut mit welchen anderen Neuronen es eine Verbindung eingegangen hat und mit welchen Neuronen wiederrum diese verbunden sind usw. usw. Trifft jetzt z.B. ein rotes Neuron auf eine Gruppe von mindestens zwei oder mehr blauen Neuronen, so wird dieses rote Neuron die Farbe der anderen annehmen. Oder anders ausgedrückt, da das rote Neuron in der Unterzahl ist, erkennt es, dass die blauen Neuronen in der Überzahl sind und schließt sich mit dem Farbwechsel zu Blau der Gruppe der blauen Neuronen an. 

Auf diese Weise entsteht ein stetiger Kampf zwischen den Farben, bzw. Daten. Am Ende wird sich immer eine Farbe, bzw. ein Datenpaket gegenüber den anderen durchsetzen. Um das besser zu visualisieren ist unten rechts eine kleine Infografik eingeblendet die immer genau darstellt, wie viel Neuronen welche Farbinformation haben. 


Die Geschwindigkeit mit der diese Entwicklung stattfindet kann aktiv über die Einstellungen gesteuert werden. 


Per „Restart“ fängt die Simulation bei jedem Klick von vorne an. „Neuron Amount“ legt fest wie viel Neuronen dargestellt werden sollen und mit „Neuron Speed“ wird die Geschwindigkeit festgelegt, mit der sich die Neuronen bewegen. Ganz wichtig ist auch die „Distance“, mit der ihr den Grenzwert bestimmen könnt, ab welcher Distanz die Neuronen miteinander kommunizieren sollen. Die Einstellungen sind mit etwas Vorsicht zu genießen, denn mehr Neuronen und eine größerer Grenzwert für die Distanz bedeuten auch deutlich mehr Berechnungen und somit Performance Verlust.
Ein Klick auf die Neuronen erweckt diese zum „Leben“ und die Simulation beginnt. Mit einem erneuten Klick könnt ihr die Simulation anhalten und natürlich auch wieder starten. Die Drehung der Neuronen ist abhängig von der Mausposition. So könnt ihr das Geschehen von allen Seiten beobachten und ggf. auch anhalten, wenn es interessante Konstellationen zum anschauen gibt
.

Besucher, die mit mobilen Geräten unterwegs sind, die sollten die Simulation am besten in einem neuen Fenster öffnen.



12/17/2015

Thresholding Crossfader

Mit dem Thresholding Crossfader könnt ihr Bilder ineinander überblenden. Bis hierher nicht wirklich spannend. Aber die Art und Weise der Überblendung ist mal etwas Anderes. Per Thresholding, bzw. per Schwellenwertverfahren lässt sich ein interessanter Effekt erziehlen, den ich so und in dieser Form, mit Hilfe der Canvas und etwas JavaScript umgesetzt, noch nicht oft gesehen habe. Das Schwellenwertverfahren ist ein extrem simpler Algorithmus zur Segmentierung von Bildern. In diesem Fall wird Schritt für Schritt (von 0 bis 255) und mit Hilfe der Helligkeit einzelner Pixel eine Segmentierung des Bildes vorgenommen. Bei jedem einzelnen Schritt werden die Pixel ausgewählt, die eine bestimmte Helligkeit haben. Diese so ausgewählten Pixel werden dann durch die des neuen Bildes ersetzt. Bei allen 255 Schritten wird eine Variable von 255 auf 0 runter gezählt. Diese Variable dient dann zum abgleichen. Bei jedem einzelnen Pixel wird geschaut, ob dieses eine geringere Helligkeit hat als der Wert der in der Variablen gespeichert ist.

Aber schaut einfach selbst. Klickt einfach auf Start unten und danach so oft ihr wollt. Auf diese Weise könnt ihr euch durch die kleine Gallerie an Matropolis Bildern klicken. Mit Hilfe der Controls könnt ihr die Geschwindigkeit bestimmen mit der die Bilder ineinander übergeblendet werden.


 
Wenn ihr Interesse an den Sources habt. Kein Problem! Hier geht es zu einer nicht minifizierten Seite bei der ihr euch den Quellcode anschauen könnt. Ich hab den Code nicht wirklich aufgeräumt, oder besonders schön gescriptet, aber wie der Effekt funktioniert sollte so trotzdem schnell klar werden. Hier die entscheidene Function:

/*
param value = 0 - 255
*/
function crossfade( value ) {

 for ( var i = 0, l = pix.length; i < l; i += 4 ) {

        var r = sourcePix[ i ];
        var g = sourcePix[ i + 1 ];
        var b = sourcePix[ i + 2 ]; 

        if ( ( r + g + b ) / 3 >= value ) {

            pix[ i ]     = r;
            pix[ i + 1 ] = g;
            pix[ i + 2 ] = b;
            pix[ i + 3 ] = 255;

        }

    }

}

Vielleicht werde ich die Tage noch ein kleines jQuery-Plugin dazu schreiben.
Bis dahin wünsche ich viel Spaß beim Bilder überblenden.

12/14/2015

Neural Network

Ein neuronales Netz? Ja, nein, vielleicht jein.
Natürlich handelt es sich bei diesem Experiment nicht um ein echtes neuronales Netz. Höchstens um einen kleinen Ausschnitt. Wenn überhaupt. Von der Anzahl an Nervenzellen  bewegen wir uns hier ungefähr auf dem Niveau eines Fadenwurms. Dessen Nervensystem besteht aus rund 300 Nervenzellen und das kommt der Anzahl der hier darstellbaren Neuronen sehr nah.
Das Ziel des Ganzen ist nicht die korrekte Darstellung von Abläufen in Nervensystemen, sondern eine einfache Visualisierung wie einzelne Neuronen miteinander Verknüpfungen eingehen können. Vielleicht könnte man hier von einer sehr vereinfachten Visualisierung von „Computational Neuroscience“ sprechen.
Die Partikel sind hierbei die Neuronen und die Verbindungslinien deren Verknüpfungen. Verknüpfungen kommen dann zustande, wenn sich zwei Neuronen soweit angenähert haben, dass eine bestimme Distanz (Kann vom User unter „Controls“ selbst festgelegt werden) unterschritten worden ist.  Je näher sich 2 Neuronen kommen, desto intensiver wird deren Verbindung und die Verbindungslinie dementsprechend stärker gezeichnet. Auf diese Weise können neuronale Netze entstehen. Natürlich funktioniert das auch umgekehrt und die gerade eben erst entstandenen neuronalen Netze können sich wieder auflösen, wenn die Entfernungen untereinander zu groß werden.
Klickt man mit der Maus auf die Darstellung und hält die Maustaste dabei gedrückt, bewegen sich die einzelnen Neuronen nach der brownschen Molekularbewegung. Auf diesem Weg kann man betrachten wie neue Verbindungen entstehen und alte Verbindungen sich auflösen. Das neuronale Netz ist bei gedrückter Maustaste also in einem stetigen Wandel. Um die Darstellung zu vereinfachen können sich die Neuronen nur innerhalb eines Würfels bewegen. Bei gedrückter Maustaste wird dieser ebenfalls sichtbar.
Ihr könnt die Anwendung direkt hier starten oder wechselt die Seite für eine bessere Performance.

Für die Darstellung kommt auch hier wieder meine kleine PixPart Engine zum Einsatz. Diese entwickelt sich munter weiter, aber ist noch immer lange nicht fertig. Daher für Interessierte nur ein paar wenige Codeschnipsel die eher allgemein, bzw. losgelöst von der PixPart Engine selbst sind. So schaut z.B. der Code aus für die brownsche Molekularbewegung eines Neurons:
particle.vectorDirection.x += Math.random() * .4 - .2;  
particle.vectorDirection.y += Math.random() * .4 - .2;  
particle.vectorDirection.z += Math.random() * .4 - .2;  

particle.vectorDirection.x *= 0.9;
particle.vectorDirection.y *= 0.9;
particle.vectorDirection.z *= 0.9;

particle.vectorPosition.x += particle.vectorDirection.x;
particle.vectorPosition.y += particle.vectorDirection.y;
particle.vectorPosition.z += particle.vectorDirection.z;
Die Verbindunglinien zeichne ich wie folgt nach dem Bresenham-Algorithmus:
function drawLine( v1, v2, c ) {

    var dx = Math.abs( v2.x - v1.x );
    var dy = Math.abs( v2.y - v1.y );

    var sx = ( v1.x < v2.x ) ? 1 : -1;
    var sy = ( v1.y < v2.y ) ? 1 : -1;

    var err = dx - dy;
    
    while( true ) {

        setPixel( v1.x, v1.y, c );

        if ( ( v1.x === v2.x ) && ( v1.y === v2.y ) )
            break;

        var e2 = 2 * err;

        if ( e2 > -dx ) { 

            err -= dy; 
            v1.x += sx; 

        }

        if ( e2 <  dy ) { 

            err += dx; 
            v1.y += sy; 

        }

    }

};
Bei Fragen, Kritik oder Anregungen würde ich mich über einen Kommentar sehr freuen.

12/11/2015

PixPart II, 3D Brownsche Planetoid Particles

PixPart Part II. Meine kleine JavaScript Engine für Partikel ist zwar noch lange nicht fertig, aber die Entwicklung schreitet voran. Einige Komponenten wie die Vector3 und die Matrix4 Klassen aus der three.js Engine hab ich nun doch wieder rausgeworfen und durch eigene Lösungen ersetzt. Damit ist die Engine wieder komplett frei von externen Komponenten anderer Engines und Pakete. Insgesamt läuft die Engine nun performanter und bietet mehr Möglichkeiten, bei gleichzeitiger Reduktion der Gesamtgröße.
Zum Testen hab ich eine kleine Anwendung geschrieben. Auch hier könnt ihr wieder einige Parameter anpassen und mit der Maus Einfluss aufs Geschehen nehmen. Das Ganze könnt ihr euch direkt hier anschauen oder in einem neuen Fenster betrachten.
     
Bei der Testanwendung handelt es sich um eine Kombination von zwei verschiedenen Techniken.
Zum einen werden die Farbinformationen einzelner Pixel aus einer 2D Grafik entnommen und auf eine 3D Sphere übertragen. Und zum anderen hab ich die Brownsche Bewegung wieder einmal eingesetzt, um bei gedrückter Maustaste die einzelnen Partikel aus der Sphere heraus zu bewegen.

Die Grafik, bzw. Textur aus der ich z.B. die Erde erzeuge sieht so aus:
Alle 5 Texturen stammen übrigens aus der Planet Texture Map Collection und sind natürlich auch in deutlich besseren Auflösungen verfügbar.

Interessant ist mit Sicherheit das Auslesen der 2D Pixelinformationen, um diese dann auf die 3D Partikel zu übertragen. Folgend der entscheidene Part aus dem Code der dafür verantwortlich ist:
var w = sourceImage.width;
var h = sourceImage.height;

for ( var x = 0; x < w; x++ ) {

    for ( var y = 0; y < h; y++ ) {

        //Farbwerte aus Grafik entnehmen
        var c = getSourceImagePixel( x, y );

        //Latitude und Longitude berechnen
        var latitude  = y / ( h / 180 ) - 90;
        var longitude = x / ( w / 360 ) - 180;

        var la = Math.radians( latitude );
        var lo = Math.radians( longitude );

        //Latitude und Longitude auf Sphere übertragen mit einem Radius
        var xP = radius * Math.cos( la ) * Math.cos( lo );
        var yP = radius * Math.sin( la );
        var zP = radius * Math.cos( la ) * Math.sin( lo );

        var particle = addParticle( xP, yP, zP, c.R, c.G, c.B, c.A );

        particleHolder.push( particle );

    }

}
An die Farbinformationen der einzelnen Pixel gelangt man beispielhaft wie folgt:  
function getSourceImagePixel( imageData, x, y ) {

    var i = ( x + y * imageData.width ) * 4;

    return { R:imageData.data[ i ],
             G:imageData.data[ i + 1 ],
             B:imageData.data[ i + 2 ],
             A:imageData.data[ i + 3 ] }

}
Zum Thema „Pixel manipulation with canvas“ findet man so viele gute Beiträge im Netz, da möchte ich an dieser Stelle nicht näher drauf eingehen.
Demnächst geht es hoffentlich weiter und ich kann mehr von der PixPart Engine zeigen. Und vielleicht erreicht die Engine auch irgendwann mal einen Stand, der sich lohnt ihn z.B. bei GitHub hochzuladen.

12/03/2015

PixPart, 3D Particles

PixPart ist der vorläufige Name meiner JavaScript Engine für Partikel im dreidimensionalen Raum, die mit Pixeln in die Canvas gezeichnet werden. Etwas unglücklich erklärt und vorläufig deshalb, weil die Engine, bzw. das ganze Projekt noch sehr am Anfang steht.
Der aktuelle Stand erlaubt aber eine kleine Demo und genau die möchte ich euch nicht vorenthalten.
Per Klick (einfach auf die untere Fläche mit dem Gesicht klicken) könnt ihr zwischen verschiedenen Modellen hin und her switchen und mit „Open Controls“ gibt es noch ein paar Einstellungsmöglichkeiten um die Anzeige zu justieren.

   
Seit dem wir Zugriff auf die Pixel der Canvas haben ist das Canvas Element noch einmal ein ganzes Stück interessanter geworden. Denn, die „Pixel manipulation with canvas“ ist unglaublich schnell. In ersten Tests konnte ich 200000 Partikel über die Canvas „huschen“ lassen und hatte immer noch satte 60 FPS!
Seb Lee-Delisle hatte dazu bereits 2012 einen sehr schönen Artikel geschrieben.
Als ich vor kurzem wieder über den Artikel gestolpert bin war er meine Inspiration für die PixPart Engine. In seinem Artikel erklärt Seb auch sehr schön und vor allem auch für Anfänger verständlich, wie er die 3D Koordinaten in 2D Koordinaten umrechnet und diese dann in die Canvas zeichnet. Hier und da ist der Code aus den Beispielen nicht optimal, aber insgesamt sehr gut lesbar und verständlich. Zum Einstieg in die Thematik Partikel, Canvas und 3D also besonders lesenswert. Cheers Seb!

Für meine Engine habe ich aber die setPixel und getPixel Funktionen anders geschrieben und vor allem das „clearRect“ zum löschen der Canvas weggelassen und durch eine deutlich schnellere Lösung ersetzt. Die Rotationen habe ich mit Hilfe einer stark modifizierten Matrix4 und Vector3 Klasse aus der three.js Engine von Mr.doob realisiert. Beide Klassen zusammen sind jetzt nur noch 10KB schwer. Vor allem aber kann man mit Hilfe der Matrix Klasse viel komplexere Berechnungen durchführen als das in Sebs Beispielen der Fall ist. Lediglich die Berechnung von 3D in 2D Koordinaten hab ich nicht wirklich abgeändert. Aber die Berechnung mit FOV hat ja auch nicht der Seb erfunden. Ich glaub ich hatte diesen
Trick mit FOV schon zu Flash5 Zeiten bei Keith Peters gesehen.
Ich will jetzt aber noch gar nicht zu viele technische Details verraten, da das ganze Projekt noch ganz am Anfang steht und sich noch vieles ändern kann. 

Demnächst dann habe ich hoffentlich mehr zu berichten. Bis dahin viel Spaß mit der Demo.
Und noch ein kleiner Tipp zum Schluss. Um noch mehr Perfomance rauszukitzeln und besonders wenn ihr im Fullscreen-Modus seid, schaltet am besten unter
„Open Controls“ Multiply“ aus und Clear ImageData“ ein.