Hint-Brushes

LePraus Hint-Brush-Artikel
Version 1.22 vom 30.12.2004

Um mit diesem Artikel etwas anfangen zu können, solltet ihr mit den r_speed-Artikeln (r_speeds und der kleine r_speed-Artikel) vertraut sein. Damit vertraut sein bedeutet, sie gelesen und verstanden zu haben!
Dieser Artikel wird euch erklären, was Hint-Brushes machen, wie man sie baut, wie man sie einsetzt, was man mit ihnen erreichen kann und was nicht. Ihr werdet dabei auch viel Hintergrund zur Half-Life-Engine erhalten, und letzten Endes werdet ihr wissen, das Hint-Brushes ein faszinierendes Hilfsmittel sind, wenn man sie geschickt einsetzt.

Außerdem habe ich alle Details ausschließlich mit den ZHLT getestet. Es kann also sein, das sich andere Compiler anders verhalten, im Normalfall sollte sich jedoch nichts Bedeutsames ändern.

Ich habe bei den Ingame-Shots absichtlich nie die r_speeds anzeigen lassen, da es sich hier um eine theoretische Bearbeitung des Themas handelt, wann und wo Hint-Brushes nützen, muss jeder für sich selbst entscheiden.

Nun aber zu den einzelnen Punkten:

Zu Beginn: Was ist ein Hint-brush?

Ein Hint-Brush ist ein Brush, der auf mindestens einer Seite die HINT-Textur hat. Im Normalfall ist diese Blau mit einem weißen H. Alle Flächen eines Hint-Brushes, die nicht mit der HINT-Textur belegt sind, müssen (!) mit der SKIP-Textur belegt sein. Zu dem Unterschied der Wirkung dieser beiden Texturen kommen wir später :)

1. Was macht ein Hint-Brush?

Ein Hint-Brush ist ein Hilfsmittel für Mapper, mit dem man den Compilevorgang beeinflussen kann. Genauer gesagt kann man damit die Leaf-Aufteilung seinen Wünschen entsprechend zurechtbiegen. Entlang den HINT-Flächen werden die Compiler dazu gezwungen, ein Leaf-Portal zu erstellen, also eine „Trennwand“ zwischen zwei Leafes. Wo immer in eurer Map ein Hintbrush war wird am Ende eine Leaf-Grenze sein, das ist garantiert. Wie ein Clip-Brush ist auch ein Hintbrush im Spiel nicht mehr zu sehen, im Gegensatz zum Clip-Brush ist ein Hint-Brush aber nicht in der BSP-Datei enthalten.
(Eigentlich ist natürlich kein einziger Brush in der BSP-Datei enthalten, da dort lediglich die Einzelflächen gespeichert sind. Es handelt sich hierbei nur um eine veranschaulichende Formulierung)
Für den Mapper bedeutet das, wenn Hint-Brushes in einer Map verwendet wurden, können diese durch ein Decompile mit WinBSPc nicht mehr rekonstruiert werden. Man erhält stattdessen Einzelbrushes, die entsprechend den Patches generiert werden.

Zur Erklärung: Links die Ursprüngliche Map, mit dem Vertextool ist der Hint-Brush angewählt, rechts ist die dekompilierte Map zu sehen, welche sich aus mehr als 3 Einzelbrushes zusammensetzt. Die fehlenden drei Seiten sind jeweils Skybrushes, außerdem habe ich jeweils noch ein info_player_start sowie ein light_environment in den Maps.
Normalerweise bringen Hint-Brushes einfach nichts, weil sie eine Fläche nur in mehrere unterteilen. Sinnlos angewendet erhöhen sie also nur die r_speeds.

2. So wirken Hint-Brushes

Die simpelste Anwendung solltet ihr aus den r_speed-Artikeln kennen, wobei sie eigentlich ihren Zweck (r_speeds reduzieren) nur in den seltensten Fällen erfüllt. Sinnvoll kann es sein, diese Methode anzuwenden um Leaf-Portal-saw-into-Leaf-Fehlern vorzubeugen. Nun aber zum Beispiel: Eine n-eckige Säule (im Beispiel n=20) splittet den Boden eines Raumes auf
Um das zu verhindern oder wenigstens einzuschränken, bedient man sich eines Hint-Brushes
hint02a.jpg
hint02c.jpg
Tatsächlich bringt das nur etwas, wenn der Raum um die Säule herum ausreichend groß ist, so dass sich die sauberere Leaf-Aufteilung tatsächlich bemerkbar macht. Sinnvoll wird es, wenn man mehrere Säulen in einem Raum hat, bei denen sich die Leafs in immer kleinere Stücke zerschneiden:

Aber auch hier muss man selbst überprüfen, inwieweit es vorteilhaft ist, Hint-Brushes einzusetzen. Bei kleinen Räumen erhöht man die r_speeds eher als das man sie senkt.

3. Eine sinnvolle Verwendungsmöglichkeit für Hint-Brushes

Angenommen, ihr habt einen schönen Gang, der um eine Ecke führt. Hinter der Ecke befinden sich r_speed-intensive Entities (z.B. irgendwelche Regale oder so), hier als Totenkopf dargestellt . . . Im Normalfall enstehen beim Compile zwei Leafes, eins blau, eins violett gezeigt.

Man kann zwar vom mittel-hellblauen Punkt aus nicht den Totenkopf sehen (ganz hellblaue Linie), aber sehrwohl ins violette Leaf. Demnach wird alles, was sich darin befindet, berechnet. Schließlich kann man von einem Punkt weiter vorne ohneProbleme den Totenkopf sehen. Wer jetzt hofft, ein einfacher Hintbrush, der Vertikal auch noch eine Leafgrenze erzeugt, würde reichen … der schaut sich das folgende Bild und den roten Pfeil an …

Die Konstellation, die man benötigt, ist folgende:

So kann man von keinem Punkt im Leaf Blau das Leaf Violett sehen, und VIS weiß das. Deshalb wird, solange man sich im blauen Leaf befindet das violette Leaf nicht angezeigt, geschweigedenn Entities in seinem Innern.

Das erklärt auch die Anwendung, die in Darthpauls Hintbrush-Artikel beschrieben wird (als Erinnerung: das mit dem Himmel und dem Raum, den man nicht sehen soll):


Im ersten Fall kann man zwar nicht vom Startpunkt der grünen Linie aus das dunkelgrüne Leaf sehen, da es aber bis zum Ende des Gangs reicht, hat man die Möglichkeit, im gleichen Leaf entlang der roten Linie das dunkelgrüne Leaf zu betrachten. In jedem Fall wird also das dunkelgrüne Leaf berechnet, auch wenn man es eigentlich nicht sehen kann. Im zweiten Fall kann man nicht einmal im Extremfall aus dem dunkelblauen Leaf ins dunkelgrüne schauen, da dazwischen das dreieckige violette Leaf liegt.

Mit ein wenig Überlegung kann man nun zusammenfassen: Mit Hintbrushes kann man r_speeds sparen, wenn man zwei r_speed-intensive Bereiche, die man normalerweise nicht gleichzeitig sieht, durch Hint-Brushes in verschiedene Leafes unterteilt, und zwar so, dass man vom einen Leaf nicht ins andere sehen kann. Es muss also mindestens ein Leaf dazwischenliegen …

4. Das Mauer-Phänomen

Vielen ist es sicher schon passiert, das sie eine Map trennen wollten und dafür eine halbhohe Mauer gebaut haben. Entsetzt stellt man fest, das die r_speeds nicht niedriger werden, also alles so ist, als wäre die Mauer garnicht da, aber warum? Die Mauer sollte doch eigentlich VIS-Blocker sein.
hint04a.jpg
Die Lösung mit r_drawflat, womit man deutlich erkennen kann, wie die Leafes aufgeteilt sind. Man sieht jetzt auch, das ich einfach 3 Prefab-Regale hinter der Mauer platziert habe, die für die r_speeds verantwortlich sind. Entlang der blauen Linie sieht man zwar dank der Mauer nicht in das Regal-Leaf, aber entlang der roten Linie ist das aus dem gleichen (!) Leaf ohne weiteres möglich.

Nun werden wir einen Hint-Brush entlang der Oberkante der Mauer basteln:
hint04c.jpg
Im Spiel sehen wir auch gleich den Effekt:
hint04d.jpg
Die Striche sind wieder Sichtlinien, die rote der Extremfall vom Rand des Leafs aus. Weiter vertiefen muss ich das nun wohl nicht mehr ;)

Ähnliche Situationen wird man immer wieder haben, und hier ist es oft sinnvoll, auch räumlich zu denken. Wenn man auch von weiter oben die Regale gern ausblenden möchte, kann man einfach ein schräges Leaf erzeugen:
hint04f.jpg

5. Der Leaf-Portal-saw-into-Leaf-Fehler


Zwei Leafportale, die auf einer Ebene liegen bezeichnet man als koplanar. Koplanare Leaf-Portale können sich normalerweise nicht sehen (logisch), da man keine gerade Linie von einem durch das andere Portal ziehen kann, und somit keine Sichtverbindung zwischen diesen Leafes möglich ist.

Der Leaf-portal-saw-into-Leaf-Fehler zeigt uns in dieser Hinsicht die Ungenauigkeiten der Computer auf. Durch minimale Rundungsfehler kann es passieren, das VIS doch in der Lage ist, eine Verbindungslinie von einem Leaf durch ein anderes in sich selbst zu ziehen. Bildlich könnte man es sich so vorstellen:
Der grün dargestellte Knick ist im Editor nicht vorhanden, lediglich nach der Aufteilung in Leaves ist er vorhanden.


Durch Ungenauigkeiten weit hinter dem Komma können die eigentlich koplanaren (in einer Ebene liegenden) Leaf-Portale für VIS diese Form annehmen. Dadurch wird es möglich, dass das Leaf A (vom Portal 1) durch die Leaves C und B (durch Portal 3) hindurch wieder zurück in Leaf A (ins Portal 2) „schauen“ kann zum Leaf.
Dieser Berechnungsfehler tritt eigentlich nur auf, wenn ein Leaf keine oder zu wenig Portale parallel zu einer der drei Grundebenen (x/y oder x/z oder y/z) hat.
Dem kann man also ganz einfach vorbeugen, indem man komplexe Objekte (oder einfach schiefe Objekte) mit einem Hint-Brush umhüllt, der so für Leaf-Portale entlang der Grundebenen sorgt.
Auf die oben beschriebene Weise entsteht übrigens auch der noch seltenere swaptransfers unmatched-Fehler bei RAD. Auch hier kann man mit einem Hint-Brush oft für einen fehlerfreien Compile-Vorgang sorgen.

Es gibt noch eine weitere Möglichkeit, wann dieser Fehler auftritt, die sehr ausführlich im Leaf-Portal-saw-into-Leaf Artikel beschrieben wird.
ACHTUNG: Diese beiden Fehler müssen nicht unbedingt diese Ursache haben, fehlerhaftes Clipping oder Vertex-Manipulation kann genauso dafür verantworltich sein!

Ich habe mir nicht die Mühe gemacht, Bilder zu machen, da es sehr schwierig ist, diese Fehler unter Laborbedingungen zu erschaffen… aber es ist gut zu wissen, wie man dagegen vorgeht. Und bei mir hat es in 4 von 4 Fällen auch geklappt.

6. HINT und SKIP-Textur

Wo liegt genau der Unterschied zwischen diesen beiden Texturen? Ganz kurz gesagt wird nur bei Hint-Textur ein Leaf-Portal erzwungen, bei Skip-Textur passiert garnichts. Soweit die Theorie. In der Praxis sieht das allerdings etwas anders aus. Die Compiler scheinen regelrecht dankbar für jede „gerade“ Ebene zu sein, die man ihnen vorwirft. So entstehen in so einem Raum mit Hint-Brush (nicht gezeigte Seiten haben alle die SKIP-Textur)…
hint06a.jpg
… solche Leafes:

Die Roten Linien sind beabsichtige Leaf-Grenzen, die Grünen Linien sind Kanten, an denen die Skip-Faces mit Worldbrushes zusammenkommen.
Wenn man die Skip-Seiten jedoch schräg clippt oder mit dem Vertextool schräg zieht, so dass kein Skip-Face einen World-Brush berührt …
hint06c.jpg
… sieht das Ergebnis so aus:

Skip-Faces erzeugen also nicht unbedingt Leaf-Portale, wenn sie allerdings eine Kante auf der Oberfläche eines Worldbrushes haben muss man mit einem Splitting rechnen. D.h., ein Hintbrush splittet durchaus mehr als man eigentlich möchte, da die Skip-Textur von den Compilern keineswegs ge“skipped“ wird. Empfehlenswert ist es also, einen Hintbrush von vornherein so zu platzieren, dass es keinen Schaden verursacht, wenn auch die Skip-Faces zu Leaf-Portalen werden sollten. Im einfachsten Fall sollte also der Skipbrush in allen Richtungen mit den Raumwänden abschließen, soweit das möglich ist.

7. Textur-Splitting bestimmen

Eine weitere Möglichkeit, vor allem um wieder r_speeds zu minimieren, ist das gezielte erzeugen von Patches. Es sollte bekannt sein, dass die Compiler eine Fläche nach spätestens 224 Units zerteilen. Bei großen Wandflächen kann man so durchaus einige w_poly sparen.
hint07a.jpg
Wenn man nun zwei Hint-Brushes in Würfelform mit den Maßen 224x224x224 verwendet, erhält man ein Patch weniger:
hint07c.jpg
Zugegeben, in diesem Fall wirkt sich das in einer Differenz von genau zwei w_poly aus, aber es ist ja auch nur ein sehr simples Beispiel. Bei komplexeren Levels kann man so eine starke Aufteilung entlang einer Wand verhindern. Und auch 2 w_polys sind für eine einzige Wand schon nicht schlecht, denn von 12 (6 Patches x 2) auf 10 ist eine Senkung um über 15%, hochgerechnet bedeutet das statt 850 nur 700 w_poly … Ok, Ok, das ist geschummelt, man hat sicher nicht nur solche Wände, aber trotzdem ist dieses Rechenbeispiel durchaus interessant. Man erkennt daran: auch Kleinvieh macht Mist.
Eine andere, sehr interessante, wenn dafür auch nicht r_speed-schonende Möglichkeit bieten Hint-Brushes bezüglich Tiling-Texturen (Auf den Gedanken hat mich TheSmilingBandit gebracht, thx). Das sind (wie bekannt sein sollte) solche mit dem Namen -?NAME wobei für das Fragezeichen eine Zahl steht. Wenn man solche Texturen verwendet, wählen die Compiler für jedes Patch zufällig eine dieser Texturen aus. Da ein Patch auf einer Mauer jedoch ohne weiteres bis zu 224 Units breit sein kann, bemerkt man oft keine Abwechslung. Um das dennoch zu erreichen, kann man den Mauerabschnitt mit Hint-Brushes bewusst öfter splitten. Nach einem kurzen Test habe ich festgestellt, das Hint-Brushes in der Form wie unten dargestellt am wenigsten Einfluß auf die restlichen Flächen und somit r_speeds haben:
hint09a.jpg
Das witzige an diesem Hint-Brush ist übrigens, das ich keine einzige HINT-Textur draufgelegt habe. Der gesamte Brush setzt sich aus SKIP-Faces zusammen … und es funktioniert.

8. Mehr Atmosphäre durch Hint-Brushes

Und ganz kurz noch eine weitere Einsatzmöglichkeit, die allerdings auch wieder auf die r_speeds geht. Wie findet ihr diesen Effekt?
hint08a.jpg
Erstaunlich, wie scharf der Schatten doch geworden ist … wie kann das sein? An den Rändern des Schattens befindet sich jeweils eine Leaf-Grenze, erzeugt durch einen Hint-Brush:
hint08b.jpg
Der Rest wurde von RAD -extra erledigt. Wichtig ist hierbei, das der Schatten nur dann so klar abgegrenzt wird, wenn die Kanten des Hint-Brushes exakt in Texturrichtung des Bodens verlaufen.
Wenn die Bodentextur also nicht gedreht ist, sollte der Hint-Brush am Raster ausgerichtet sein. Wenn man die Textur um 45 Grad dreht, sollte auch der Hintbrush um 45 Grad gedrehte Seiten haben, wobei es dann durchaus möglich ist, den Hintbrush einen rechten Winkel aufspannen zu lassen.
Wenn die Leaf-Grenzen sich nicht exakt an der Textur orientieren, ergibt sich dieser Effekt leider nicht.

Einen weitere Möglichkeit für die Verwendung von Hint-Brushes hat Khan Reaper Kerensky aus dem TheWall.de-Forum getestet:
Ich hab grad noch ne sinnvolle Verwendung für hint und skips gefunden. Ich hab mir nen kleinen Testraum mit 4 Lichtern gebaut. Also ein absichlicher „Too Many Direct Light Styles on a Face“. So in die Mitte hab ich dann ein hint gesetzt (skips schief damit se nicht noch mehr splitten). Dadurch wurd zwar in keiner Weise vis geändert (in meiner Map zumindest) und von den r_speeds kann sich auch nicht so viel getan haben ;), aber der lightfehler ist wech und alle 4 Lichter in einem Raum werden richtig darstellt.
Danke von mir an dieser Stelle :)


Zusammenfassend kann man sagen, Hint-Brushes sind zwar kein Allzweckmittel, können aber von Zeit zu Zeit Fehler beseitigen, r_speeds verringern helfen oder einfach um an einigen Stellen die Compiler zu schönen Effekten zu überreden.
Wer den Artikel verstanden hat, wird in Zukunft auch von sich aus Leaf-bewusster mappen… zumindest hoffe ich das.

Und selbst wenn man nach der Lektüre nicht unbedingt das Bedürfnis verspürt, seine Maps mit Hintbrushes zu optimieren, so weiß man doch, welche Möglichkeiten man hätte und weshalb die Compiler an manchen Stellen völlig unerwartet reagieren.
PS: Nein, es gibt keine Beispielmaps, wer sich die Beispiele anhand der Abbildungen nicht selbst nachbauen kann, sollte vielleicht doch noch einmal zu den Grundlagen zurückkehren…

Die Verwendung aller Dokumente einschließlich der Abbildungen ausschließlich zu nichtkommerziellen Zwecken. Verbreitung des Dokuments auf Speichermedien, (insbesondere auf CD-ROMs als Beilage zu Zeitschriften und Magazinen oder sog. "Mission-Packs" etc.) ist untersagt.
 
half-life/tutorials/hint-brushes.txt · Zuletzt geändert: 2005/01/29 13:16 von Adrian_Broher