request_url_withoutHTTP=,canonical_url_withHTTP=,canonical_url_withoutHTTP=,request_url_withoutHTTP_realspaces=. Javascript (Seite 1 von 2) « Tags « Blog « Bernhard Häussner
Bernhard Häussner
Tags: Artikel mit dem Tag «Javascript» durchstöbern

Javascript in Photoshop

22.10.2011, 13:32
Photoshop-Skripting-Beispielbild

Photoshop-Skripting-Beispielbild

Als ich kürzlich eine ganze Reihe Ausweise mit Namen ausfüllen musste, habe ich mir angeschaut, wie man Photoshop CS3 automatisieren kann. Ich war erstaunt herauszufinden, das PS mit Javascript gesteuert werden kann, neben den zusammenklickbaren Makros, VBScript und AppleScript.

Hello-Word-Beispieldateien

Da der komplette Code etwas länger ist, habe ich eine Beispiel-PSD und alle Skripte auf Github online gestellt. Dort unter Downloads findet sich eine zip-Datei mit allem Nötigen, um das hier beschriebene Hello-World-Skript auszuführen.

Dokumentation

Das Photoshop-Scripting ist sehr ausführlich dokumentiert. Zunächst gibt es im Ordner C:\Programme\Adobe\Adobe Utilities\ExtendScript Toolkit 2\SDK zwei Dokumente: Einmal Adobe Intro to Scripting.pdf, welches man lesen sollte, wenn man „noch nie programmiert hat“ oder nicht so genau weiß, was Anwendungen skripten allgemein ist.

Außerdem JavaScript Tools Guide CS3.pdf. Hier findet sich zunächst ein Überblick über das IDE von Adobe (ich habe aber alles direkt in kwrite geschrieben) und dann folgen die Dokumentationen zu den Libraries für Dateisystem, UI, HTTP, Sockets, und vieles weitere. In dem Dokument wird regelmäßig auf Beispieldateien aus dem Brige SDK hingewiesen, dieses findet sich hier.

Die Photoshop-Spezifischen APIs stehen in der Photoshop Javascript Referenz. Photoshop stellt ein DOM zur Verfügung.

Erstellen der Photoshop-Datei

Zuerst kann man eine ganz normale Photoshop-Datei erstellen. Gute Ebenen-Organisation erleichtert später das Skripten. Wenn möglich, packt man alle Ebenen, die bearbeitet werden sollen, zusammen in eine Gruppe (Ordner). Dann findet man sie im Skript leichter wieder. Wenn man, wie ich, mehrere Ausweise o.ä. auf eine DIN-A4-Seite zusammenstellt, kann man jeden Ausweis gleich und in einer eigenen Gruppe anlegen, auch das macht das Skripten einfacher.

Skripte ausführen

Um ein fertiges Skript auszuführen klickt man im Photoshop-Menü Datei > Skripten > Durchsuchen und wählt die .jsx Datei. Das Skript läuft sofort los, eventuell erscheinen Fehlermeldungen als Dialogbox.

Exkurs: Eingabe-Daten verarbeiten

Man könnte zwar rein technisch gesehen mit Javascript die Daten von einem FTP-Server laden, dann irgendwie verarbeiten und letztendlich daraus die Bilder generieren. Ich habe mich jedoch darauf beschränkt, die Daten von einer Tabelle auf einer Webseite zu kopieren (sie sind dann Tabulator-Getrennt in der Zwischenablage) und sie mit awk in ein entsprechendes JSON-Format zu bringen:

awk 'BEGIN{RS="\r\n";FS="\t+"} {print "{planet:\"" $1 "\",comment:\"" $2 "\"},"}' planeten.raw.txt > planeten.json.txt

Da ich auf Windows arbeite (awk läuft auf Linux, die Dateien liegen in einem Samba-Share), musste ich awk sagen, dass die Zeilen auch noch einen Wagenrücklauf beinhalten. Die entstandenen JSON-Daten habe ich dann in das Skript hart kodiert:

var data=[
  {name:"world"},
  {name:"venus"},
  {name:"mars"},
  {name:"pluto",
   comment:"You're not a real planet though. But still, welcome. "}
];

Photoshop-Ebenen bearbeiten und speichern

Hauptsächlich soll das Skript Photoshop-Textebenen mit neuen Texten versehen. Hierzu gibt es in der Dokumentation auch Beispiele. Im Wesentlichen iteriert man durch die Daten, findet in layerSets den Ebenen-Ordner mit den Texten, und bearbeitet dann die Eigenschaft textItem.contents der verschiedenen artLayers (Ebenen). Der Code sieht dann so aus:

for (var dataI = 0; dataI < data.length; dataI++) {
    
  var textGroup = activeDocument.layerSets[0];
  
  textGroup.artLayers[0].textItem.contents=
    "Hello, "+data[dataI].name+"!";
  
  if(data[dataI].comment) {
    textGroup.artLayers[1].textItem.contents=
      data[dataI].comment;
  } else {
    textGroup.artLayers[1].textItem.contents=
      "Welcome to Photoshop scripting.";
  }
  
  // code zum speichern
  
}

Speichern und Exportieren

Ich bearbeite immer das activeDocument und speichere das neue Bild dann als Kopie. Hier überschreibt Photoshop bereits generierte Dateien ohne nachzufragen. Die Speicher-Optionen können als XxxSaveOptions-Objekte mitgegeben werden.

// Erstellen der Optionen fuer JPEG-Export:
var jpgOpts = new JPEGSaveOptions();
jpgOpts.embedColorProfile=true;
jpgOpts.quality=12; // hoechste Q

// Dokument speichern:
activeDocument.saveAs(filename,jpgOpts,true/*=als Kopie*/);

Den neuen Pfad generiere ich aus dem Dateinamen das aktuellen Dokuments und einer fortlaufenden Nummer. Dazu benutze ich eine Reihe nützlicher Funktionen. Damit ich diese nicht in jeder Skript-Datei einfügen muss, benutze ich die include-Funktion von Adobes ExtendedScript:

#include util.jsxinc

Der vollständige Code der util.jsxinc findet sich im Github-Repository.

Benutzeroberfläche

Bisher wird einfach nur eine Sanduhr angezeigt während das Skript läuft, also erstelle ich ein Fenster mit einem Fortschrittsbalken. Man kann auch komplexere UIs zur Eingabe von Parametern usw. erstellen, aber dies lohnt sich vermutlich selten. Ein Fortschrittsbalken mit Cancel-Funktion ist jedoch nicht so schwer zu erstellen. Im Wesentlichen benötigt man dies:

var dlg = new Window('window', _(names));
dlg.progressbar = dlg.add('progressbar');
dlg.progressbar.preferredSize = [400,20];
dlg.show();

// Zur Haelfte fertig:
dlg.progressbar.value = 50;

Hilfslinen-Skript

Ein weiteres Skript kann Hilfslinien erstellen. Am Besten kopiert man es in den Ordner Adobe Photoshop CS3\Vorgaben\Skripten, damit es immer im Skript-Menü auftaucht. Ich finde es immer extrem nervig, für Druckränder und Mittellinien die ganzen Hilfslinien zu erstellen. Genauso nervig ist es, für jedes Druckformat eine Vorlage zu basteln. Lieber generiere ich die Hilfslinien mit diesem kurzen Skript.

ExtendScript hat auch noch weitere Features, wie Reflection und Operator Overloading, welches dann bei den UnitValues Rechnen mit Einheiten ermöglicht. In ExtendScript geht das:

alert( (UnitValue(3,"mm") + UnitValue(7,"pt")*0.9).as("cm") );

Da es für die Hilfslinienerstellung keine Funktionen gibt, habe ich die Methode createGuide(offs,orientation) mit dem ScriptListener erstellt. Man kopiert Adobe Photoshop CS3\Skript Handbuch\Hilfsprogramme\ScriptListener.8li nach Adobe Photoshop CS3\Zusatzmodule\Automatisieren und startet PS neu. Dieses Plugin erstellt auf dem Desktop ein ScriptingListenerJS.log, in dem die u.A. die aufgenommenen Aktionen als Javascript-Code gespeichert werden. Diesen Code muss man dann noch parametrisieren und erhält so für alles, was man in Photoshop anklicken kann, den entsprechenden Code.

Auch die Ressourcen-Deskriptoren habe ich im Skript verwendet. Mit ihnen kann man aus einem String direkt einen ganzen UI-Baum erstellen.

Zusammenfassung

Ressourcen zum Text:

Das Skripten von Photoshop ist schon nach kurzem Einarbeiten für den Javascript-Kenner wohl wesentlich einfacher als das zusammenklicken von Aktionen und Stapelverarbeitungen. Wer sich intensiver mit der Dokumentation befasst kann darüber hinaus sehr flexibel mit Daten aus verschiedenen Quellen automatisiert Dokumente erstellen.

Kommentare: keine

Symmetrisch Zeichnen

17.12.2009, 10:43

Neben Symmetrie in der Natur bin ich auch begeistert von den Symmetrien, die der Computer erstellen kann. Und was wäre diese Symmetrie ohne die, für den Computer typische, Interaktivität? Also habe ich (zunächst mit Processing aber dann mit) HTML5-Canvas eine kleine Javascript-Sache gebastelt, mit der man direkt im Browser symmetrisch zeichnen kann.

Irgendwie macht das Spaß und, naja, es sieht auch oft erstaunlich gut aus.

[Updated 2011-09-29] Da mir das einfache herumzeichnen schnell zu langweilig wurde, habe ich das Script immmer weiter ausgebaut. Deswegen finden sich unter dem Link nun mehrere Variationen, die es sich auszuporbieren lohnt![/Updated]

Zum Zeichenbrett

Und hier noch ein Video:


Drawing Symmetry (6)

Viel Spaß beim Malen!

Kommentare: 2 Einträge

Javascript Regular Expressions Beispiele

03.11.2009, 18:18

Viele Javascript-Tutorials zum RegExp-Objekt benutzen die RegExp.$1-Notation und andere unschöne Dinge. Außerdem gibt es mehrere nahezu äquivalente Funktionen, was Reguläre Ausdrücke angeht. Darum habe ich ein Bisschen herumgespielt mit den Funktionen S.match(R), R.exec(S), R.test(S), S.split(R), S.replace(R) und S.search(R). Hier ist die kleine Referenz mit viel Beispiel, mit der ich hoffe arbeiten zu können:

RegExp-Objekte erstellen

// short constructor
var regexp=/a(b?c)/i

// long constructor
var regexp=new RegExp("a(b?c)","i"):
// -> allows runtime configuration
var char="a";
var regexp=new RegExp(char+"(b?c)",'i');

In der Praxis wird man fast immer den kurzen Konstruktor verwenden. Manchmal lässt sich ein dynamisches Erstellen des RegExps vermeiden, indem man den Treffer überprüft.

Finden mit String.match(RegExp) und RegExp.exec(String)

// match: basic usage
"a".match(regexp);   //  null
"abc".match(regexp); // ["abc", "bc"]
// -> "i"-flag: caseinsensitive
"Ac".match(regexp));  // ["Ac", "c"]
"acb".match(regexp); // ["ac", "c"]

// exec: same but method of regexp
regexp.exec("a");   //  null
regexp.exec("abc"); // ["abc", "bc"]
regexp.exec("Ac");  // ["Ac", "c"]
regexp.exec("acb"); // ["ac", "c"]

Bis auf wenige Ausnahmen (siehe unten) sind die beiden Funktionen gleich. Zurückgegeben wird ein Array mit dem gesamten passenden Teil und den im regulären Ausdruck eingeklammerten Teilen.

Prüfen mit RegExp.test(String)

// test: just booleans
/^abc$/.test("abc"); // true
/^abc$/i.test("AbC"); // true
/^abc$/.test("abcd"); // false

Diese Funktion ist zum Validieren von Eingaben recht praktisch, wenn es nicht auf den Inhalt des Strings ankommt.

Teilen mit String.split(RegExp)

// split: arrayify stings
"a,b,c.d".split(/\.|,/) // ["a", "b", "c", "d"]
"a,.b- c .d_e".split(/[.,-_]/) // ["a", "", "b", " c ", "d", "e"]
"a,.b- c .d_e".split(/[.,-_\s]*/) // ["a", "b", "c", "d", "e"]

Das Teilen kann auch mit einem normalen String geschehen, aber mit einem RegExp lassen sich, wie in diesem Beispiel demonstriert erweitere Funktionen implementieren, wie mehrere mögliche Trennzeichen oder das kürzen von Whitespace und leeren Elementen.

Lokalisieren mit String.search(RegExp) und RegExpResult.index

// search: match position
"0123b56b".search(/b/g); // 4
"0123b56b".search(/x/g); // -1

// index: match position, too
/b/.exec("0123b56").index; // 4
"0123b56".match(/b/).index; // 4
// -> "g"-flag:global
/b/g.exec("0123b56b").index; // 4
"0123b56b".match(/b/g).index; // undefined

Interessant ist, dass match und global sich nicht vertragen. Irgenwie ist es schon eine rechte Eigenart dass sich gobale und nicht-globale Ausdrücke so startk unterscheiden, daher würde ich RegExp-Objekte nicht zu weit durch Methodenaufrufe schicken.

Ersetzen mit String.replace(RegExp,replacement)

// replace
var string="ab-ghi-abc-hl-ac"
string.match(regexp); // ["abc", "bc"]
string.replace(regexp,"#")); // "ab-ghi-#-hl-ac"

Globales Finden und Ersetzen

// more global
var regexp2=new RegExp(regexp.source,'g')
string.replace(regexp2,"#"); // "ab-ghi-#-hl-#"
string.match(regexp2); // ["abc", "ac"]
// loop like that:
regexp2.exec(string); // ["abc", "bc"]
regexp2.exec(string); // ["ac", "c"]]
regexp2.exec(string); // null
regexp2.exec(string); // ["abc", "bc"]

Hier unterscheiden sich match() und exec()! Während match() ein Array der allen Treffern aus den kompletten Trefferstellen liefert, liefert exec(), wie beim nicht-globalen, pro Fundstelle je ein Array inclusive Klammerstellen. Um mit exec() alle Treffer zu erhalten, kann man z.B. eine while-Schleife verwenden.

Backreferences

// backreferences
/([ab])c\1/.test("aca"); // true
/([ab])c\1/.test("bcb"); // true
/([ab])c\1/.test("bca"); // false

// replacement backreference
// notice 1-9 limitation
"ll mm kk kx a Bb lL".replace(/([lkb])\1/gi,"$12")
"l2 mm k2 kx a B2 l2"
// beyond 1-9
"abcdefghijklmnopqrst".replace(/(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)/i,"$13-$1-$13+++") // "m-a-m+++qrst"
"abcdefghijklmnopqrst".replace(/(.)(?:.)(?:.)(?:.)(?:.)(?:.)(?:.)(?:.)(?:.)(?:.)(?:.)(?:.)(.)(?:.)(?:.)(?:.)/i,"$2-$1-$13+++") // "m-a-a3+++qrst"
// get a $
"ab".replace(/(.)/,"$$1") // $1b
"ab".replace(/(.)/g,"$$1") // $1$1
// special backrefs:
"abcdefg".replace(/(d)e/,"[ $`-$1-$' (inst $&) ]") // "abc[ abc-d-fg (inst de) ]fg"

Richtig interessante Dinge lassen sich machen mit Backreferences. Grundsätzlich können doppelte Vorkommen von passenden Teilen geprüft werden. Beim Ersetzen sind sie essenziell für Umformatierungen.

Spezialitäten

// special firefox shortcut:
/a/("cba") // a
/a(.)/("acbab") // ["ac", "c"]
// Ein Bonbon:
/\\/("\\")//["\"]
// Noch eines:
function _(é) {var ì=Array,í=RegExp,è=["join","length","replace"],î=[],_
="\x31",_=_*_,ë=_+_+_*_;for (var i=ë;i>=_;i--) {î[î[è[_]]]=("((\\\x64)"+
(new ì(i)[è[_-_]]("\\"+(ë-i+_)*(_+_)))+")");}var î=new í(î[è[_-_]]("|"),
"\x67"),ï=function(){var I=arguments;for(var i=ë;i>=_;i--){var j=(_+_)*(
ë+_-i);if(I[j]) {return i+I[j];}}},ì="",í=_+ì;for (i=_-_;i<é;i++) {ì+=(i
+"\x20"+í+"\n");í=í[è[_+_]](î,ï);}return ì;}alert(_(9));

Der Firefox-Shortcut könnte zwar praktisch sein, wird aber nicht von vielen Browsern unterstützt, und ist auch ein bisschen zu abstrakt.

Letztere Funktion benutzt Backreferences sowohl im RegExp als auch im Ersetzungstext, zudem ersetzt sie Rekursiv und baut das RegExp dynamisch. Außerdem habe ich sie ein bisschen verschlüsselt, da die Berechnung der ausgegebenen Zahlenreihe eigentlich ein Rätsel ist. Wenn man allerdings weiß, dass ich RegExp verwende, fällt die Lösung leichter, und wenn man es gelöst hat, weiß man vielleicht auch warum es ein perfekter Vorwand ist, um sich etwas mit Regulären Ausdrücken zu beschäftigen.

Such-Wiki zu „javascript regexp“

Kommentare: 2 Einträge

Firefox-Tricks für Webentwickler

30.10.2009, 10:12
userContent.css

userContent.css

Der populäre Webbrowser Mozilla Firefox zeichnet sich unter anderem durch viele Add-Ons aus. Jedoch wird nicht jede persönliche Vorliebe durch ein Add-On abgedeckt. Doch wer sich etwas mit Javascript und CSS auskennt, kann auch selbst kleine Einstellungen machen, ohne viel Aufwand. Dazu gibt es mindestens diese vier Möglichkeiten:

Anpassen von userContent.css und userChrome.css

Diese beiden Dateien befinden sich im Unterordner chrome des Firefox-Profilordners und müssen meistens angelegt werden. Sie sind (fast) ganz normale CSS-Stylesheets; Die userChrome.css enthält CSS-Regeln, die auf das XUL-Interface des Browsers, also alle Menüs, Toolbars etc. angewendet werden. So ist es leicht, z.B. die Schriftgröße der Bedienelemente zu vergrößern, oder der Adressleiste eine Monospace-Schriftart zu verpassen. Auf mozilla.org gibt es weitere Beispiele für userChrome.css.

Die Datei userContent.css enthält CSS-Regeln, die auf die angezeigten Webseiten angewendet werden. Ich benutze die Datei, um mich vor gewissen Links zu warnen: Zum Beispiel mag ich es nicht von Google immer auf experts-exchange.com zu klicken. Darum habe ich diese kleine Regel eingebaut, die mittels CSS3-Attribut-Selektor alle Links zu dieser Seite durchstreicht und verblasst:

a[href^="http://www.experts-exchange.com/"] {opacity:0.3 !important; text-decoration: line-through ! important;  }

Das !important bewirkt, dass die Regel die bereits vom Webseitengestalter gesetzten Regeln überschreibt.

Die Regeln lassen sich glücklicherweise auf bestimmte Seiten beschränken, so wie hier:

@-moz-document url(http://twitter.com/), url(http://twitter.com/home)
{
.latest-status {background-color:#FFFFC9;}
}

Diese Regel hinterlegt z.B. die letzte selbst geschriebene Nachricht im Stream von twitter.com mit einem leichten Gelb. Das erleichtert zu sehen, was wann passiert ist.

Eigene Sidebars

Wer Plattform-übergreifende Widgets basteln will, kann auf die Firefox-Sidebar zurückgreifen. In dieser lassen sich beliebige Webseiten anzeigen. Dazu muss man lediglich ein besonderes Lesezeichen erstellen, dass dann immer in der Sidebar geöffnet wird:

Sidebar Lesezeichen

Sidebar Lesezeichen

Man kann also wenn man etwas Bildschirmplatz opfern will, selbst gemachte Widgets anzeigen lassen. Der Link im Screenshot verweist auf eine Seite, die nur ein Textfeld enthält, um schnell Notizen zu machen oder als erweiterte Zwischenablage. Doch die Möglichkeiten sind nahezu unbegrenzt (Monitoring, Feeds, ...?).

Bookmarklets

Bookmarklets führen auf Knopfdruck bestimmte Javascript-Schnippsel auf einer Webseite aus, und funktionieren dabei nicht nur im Firefox. Dazu muss man den JS-Code von Zeilenumbrüchen befreien, alle Leerzeichen mit %20 kodieren und das Ganze dann umschließen mit:

javascript:(function(){/*here goes the code*/})();

So wird das Script zu einem Javascript-Link, der dann als Lesezeichen gespeichert werden kann. Ich habe mir z.B. ein Twitter Bookmarklet gebastelt. Außerdem einen DOM-Performance-Tester:

javascript:(function(){var%20d=0,l=500,n=document.getElementsByTagName('*').length;for(var%20i=0;i<l;i++){document.body.style.display='none';var%20s=Number(new%20Date());document.body.style.display='';var%20h=document.body.clientHeight;d+=Number(new%20Date())-s;}alert('Reflow:%20'+(d/l)+'%20ms%20('+Math.round(1000/(d/l))+'%20fps)\nDOM-Nodes:%20'+n+'\nRewlow%20per%20node:'+Math.round(1000000*d/(l*n))+'%20ns');})()

DOM-Benchmark

Das Kurze Script ermittelt, wie lange der Browser für einen Seitenaufbau braucht und wie viele DOM-Knoten das Dokument enthält. Es ist praktisch, wenn man komplexere Javascript-Animationen oder ähnliches erstellt, die langsam wirken. Dann offenbart der Test, ob nicht zu viele DOM-Knoten oder komplizierte CSS-Regeln die Seite verlangsamen.

Faustregel: Je weiter hinten ein Selektor steht, desto weniger Elemente sollten auf ihn passen, also li #id ist schneller als #id li, wobei sich das besonders in Verbindung mit CSS-Expressions bemerkbar macht.

Greasemonkey

Um auf bestimmten Seiten JS-Code auszuführen, gibt es das Firefox-Plugin Greasemonkey. Zu diesem Add-On gibt es nicht nur ein großes Repositorium existierender sog. Userscripts, sondern man kann auch schnell ein eigenes Script erstellen, um auf bestimmten Webseite irgendetwas anzupassen. Außerdem kann man jQuery benutzen mit folgender Zeile im Header:

// @require http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js

Ich habe z.B. ein Quick Search-Userscript gebastelt, welches beim Auswählen von Text ein kleines Menü öffnet, sodass ich den Text z.B. googlen, übersetzen oder twittern kann.

Es gibt also mehr effektive Möglichkeiten Firefox anzupassen, als das installieren von Add-Ons.

Kommentare: keine

3D-Perspektive mit einer kurzen Formel

04.09.2009, 19:07
3D-Effekt mit Javascript

3D-Effekt mit Javascript

Für die Gestaltung von 3D-Effekten, sind zwar duzende Hardware-beschleunigte Toolkits parat, doch im Fall von HTML-Canvas bzw. auf Webseiten generell sieht das Angebot nicht so reich aus. Das hat mich dazu bewegt, selbst einen kleinen Blick in die Mathematik hinter 3D-Projektionen/3D-Perspektive zu werfen. Meine Erkenntnisse konnte ich in einer kurzen Formel zusammenfassen.

Wer sich nicht für die Mathematik interessiert, kann natürlich flash oder eine der vielen Canvas-3D-Librarys verwenden.

Das Prinzip hinter der 3D-Projektion ist meist das einer Lochkamera. Lichtstrahlen fallen vom abzubildenden Punkt im Raum durch ein Loch und auf einen Schirm. Diese Art der Projektion war eine der ersten bekannten und mit ihrer alten Bezeichnung „camera obscura“ (lat. für dunkle Kammer, die in der der Schirm angebracht war) namensgebend für die heute auf Linsenoptik basierenden Kameras.

Die Lochkamera ist leider nicht so lichtstark wie die Linsenoptik und ihre Schärfe ändert sich nicht mit der Entfernung, sondern mit der Größe des Lochs.

Im Gegensatz zur Linsenoptik ist die Lochkamera aber durch den einfachen Strahlensatz zu berechnen. Mit dem Strahlensatz kann man ganz einfach die Koordinaten eines Punktes im Raum umrechnen in Koordinaten auf dem Schirm. Dazu genügt folgende Funktion:

F:ℝ³→ℝ², F(x,y,z)= P( x*d / z | y*d / z ) ; d: distance to screen

Dass diese Funktion klappt, zeigt dieses Beispiel. Hier eine Graphische Erläuterung:

Strahlensatz für Perspektive. Schwarz: Abzubildender Punkt/Lichtstrahl, Blau: Kamera, Grün: Kameraparameter Bildweite, Rot: Koordinate auf dem Schirm, Lila: Ursprungskoordinaten

Strahlensatz für Perspektive. Schwarz: Abzubildender Punkt/Lichtstrahl, Blau: Kamera, Grün: Kameraparameter Bildweite, Rot: Koordinate auf dem Schirm, Lila: Ursprungskoordinaten

Wegen dem Strahlensatz gilt x' / x = d / z, aufgelöst x' = d*x / z, analog für die y-Koordinate.

Etwas logischer wäre vielleicht der Schirm hinter dem Loch, vor allem da Objekte näher an die Kamera heran kommen können, doch so kann man sich den Schirm wie den Computerbildschirm vorstellen, durch den man in die Raumillusion hineinschaut.

Diese Formel erledigt die Abbildung in der Kamera. Jedoch muss der Punkt bereits in Koordinaten relativ zur Kamera gegeben sein. Da man normalerweise Punkte zunächst durch ein Weltkoordinatensystem definiert, muss man sie erst transformieren.

Bei meinem einfachen Beispiel beschränkt sich die Transformation zunächst auf eine Verschiebung entlang der z-Achse und später habe ich noch eine Rotation um die y-Achse hinzugefügt. Diese Koordinatenumrechnungen lassen sich in Transformationsmatrizen beschreiben.

Dann fehlt eigentlich nur noch die Darstellung. Im Beispiel wird der Text durch einfache CSS-Manipulationen an die richtige Position gebracht, und die Kreise werden mit dem canvas-Element gerendert.

Mit einem solchen Modell lassen sich schon einfache Drahtgitter problemlos darstellen (Demo), da eine Kante zwischen zwei Punkten im Raum auch eine Strecke zwischen zwei Punkten auf dem Schirm darstellt, und uns somit die Berechnung dieser Bildpunkte erspart. Für eine ausgefeiltere Darstellung kann man Dreiecke oder Polygone verwenden (Demo), für die ungefähr das selbe gilt, nur dass z.B. ihr Winkel zu einer Lichtquelle für die Kolorierung verwendet werden kann

Für nahezu realistische Lichteffekte bedarf es allerdings eines anderen Modells, genannt Raytracing, bei dem man den Weg rückwärts geht und bei der Kamera anfängt. Das wurde übrigens auch schon in Javascript umgesetzt, ist aber für Echtzeit-Anwendungen eher ungeeignet (vielleicht kommen bald die ersten Computerspiele mit der - in Realtime - noch neuen Technik).

Kommentare: 3 Einträge
[ Seite 1 2 ] Nächste Seite »
 
Χρόνογραφ
© 2008-2017 by Bernhard Häussner - Impressum - Login
Kurz-Link zur Homepage: http://1.co.de/