Triangle Mesh Compression

Werbung
Universität Koblenz–Landau
Fachbereich Informatik
Triangle Mesh Compression
Dominik Breuer
Matrikelnummer 9720116
Seminar Computergraphik
betreut von Prof. Dr.-Ing. H. Giesen
Wintersemester 2000/2001
Vortrag vom 11. April 2001
Inhaltsverzeichnis
1
Einleitung
1.1 3D-Darstellungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2 VRML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
3
3
2
Kompressionsverfahren
4
3
,,Triangle Mesh Compression”
3.1 Connectivity Encoding . . . . . . . . .
3.1.1 Flussdiagramm Encoding . . .
3.1.2 Beispiel Encoding . . . . . . .
3.1.3 Flussdiagramm Decoding . . .
3.1.4 Beispiel Decoding . . . . . . .
3.1.5 Komprimierung der Befehlsliste
3.2 Vertex Coordinate Compression . . . .
4
Ergebnisse
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5
5
8
9
10
11
12
12
14
2
1
Einleitung
Mit dem Beginn der großen Verbreitung des Internets hat auch die Menge an multimedialen Inhalten kontinuierlich zugenommen. Anfang der 90er Jahre bestand ein Großteil der
Internetseiten aus einfachen Textdarstellungen mit vereinzelten Bildern. Mit der Zeit stieg
der Anteil der Bilder immer weiter an. Hinzu kamen immer häu£ger auch animierte Bilder, Soundeffekte und Scriptsprachen. Durch diese Entwicklung steigt auch der Bedarf an
größerer Bandbreite zur Übertragung der Inhalte stark.
Aufgrund der begrenzten Bandbreite von herkömmlichen Datenleitungen wäre ein Transport der Daten in unkomprimierter Form nur schwer möglich. Daher verwenden die im
Internet verwendeten Dateiformate für Bild- und Toninformationen Komprimierungsverfahren zur Reduzierung der Datenmenge.
1.1
3D-Darstellungen
Die bisher angesprochenen Bildformate dienen alle der Darstellung von 2D-Bildern. Immer häu£ger werden jedoch auch 3D-Darstellungen verwendet. Diese k önnen jedoch nicht
mehr mit herkömmlichen Kompressionsverfahren komprimiert werden, da es sich bei den
Bilddaten nicht mehr um Bildpunkte, sondern um Gittermodelle handelt.
Diese Gittermodelle bestehen aus einzelnen Dreiecken, aus denen die 3D Struktur aufgebaut wird. An zu speichernden Daten fallen so die Koordinaten der Dreieckspunkte, sowie
die verbindenden Kanten zwischen den Punkten an. Ein im Internet verwendetes Format
zur Übertragung dieser Koordinaten- und Kantenlisten ist VRML.
1.2
VRML
VRML ist die Abkürzung für ,,Virtual Reality Modeling Language” und dient der Beschreibung von 3D Welten. Das Format unterstützt die vollständige Beschreibung von
dreidimensionalen Szenarien mit gerenderten Objekten, Lichtquellen, Ober¤ächentexturen
und realistischen Effekten.
Gespeichert werden die Daten in der Version VRML97 als ASCII Zeichen. Die Koordinaten- und Kantenlisten werden also in unkomprimierter Form gespeichert. Daraus resultieren, mit zunehmender Komplexität der 3D Modelle, sehr große Dateien. Einzige
Möglichkeit zur Reduzierung ist das ,,Packen” in Formaten wie ,,Zip”. Doch selbst in dieser Form benötigt ein relativ einfach aufgebautes Modell, wie z.B. ein Triceratops mit 2832
Knoten, noch ein Größe von 44 KByte.
Aufgrund dieser Problematik sollen in folgenden VRML Versionen die Daten nicht mehr
im ASCII, sondern im Binär Format gespeichert werden. Ermöglicht wird dies durch die
Verwendung von Kompressionsalgorithmen für die verwendeten Gittermodelle.
3
2
Kompressionsverfahren
Wie bei anderen Kompressionsverfahren, z.B. bei Bild-, Audio- und Videokompression,
kann bei der Kompression von Gittermodellen zwischen verlustbehafteten und verlustfreien
Verfahren unterschieden werden.
Bei den verlustbehafteten ,,Mesh Reduction” Verfahren handelt es sich allerdings nicht um
Kompressionsverfahren im eigentlichen Sinne. Die Datenreduktion wird hier durch eine
Reduzierung der Anzahl an Knoten und Kanten erreicht. Allerdings stellt dieser Vorgang
noch keine Komprimierung dar. Daher kann ,,Mesh Reduction” als eine Mögliche Vorstufe
zur verlustfreien Komprimierung angesehen werden.
Die verlustfreien Verfahren sind sich in ihren wesentlichen Bestandteilen sehr ähnlich. Der
Komprimierungsvorgang wird meist in zwei Teilbereiche gegliedert:
• Connectivity Encoding
Hierbei werden die Kanten der Dreiecke in einer bestimmten, Verfahren abhängigen, Form kodiert. Dabei wird erfasst, wie die Dreieckspunkte durch die einzelnen
Kanten miteinander verbunden sind.
• Vertex Coordinate Compression
Der zweite Schritt dient der Komprimierung der Koordinaten der Dreieckspunkte.
Diese sind erforderlich um mit Hilfe der Kanteninformationen das ursprüngliche Gittermodell zu rekonstruieren.
Durch die Verbindung dieser beiden Komprimierungsschritte werden alle notwendigen Daten der Gittermodelle erfasst. Beim Dekomprimieren kann so die vollständige Struktur,
ohne Verluste, wiederhergestellt werden.
In den letzten Jahren wurden viele solcher Verfahren zur ,,Mesh Compression” vorgestellt.
Darunter waren unter anderem die folgenden Verfahren:
• Geometric Compression Through Topological Surgery [1]
(1998, Gabriel Taubin - Jarek Rossignac)
• Triangle Mesh Compression [2]
(1998, Costa Touma - Craig Gotsman)
• Real Time Compression of triangle mesh connectivity [3]
(1998, Stefan Gumhold)
• Edgebreaker: Compressing the incidence graph of triangle meshes [4]
(1999, Jarek Rossignac)
Im nächsten Abschnitt wird mit ,,Triangle Mesh Compression” eines der Verfahren näher
erläutert.
4
3
,,Triangle Mesh Compression”
Das Komprimierungsverfahren ,,Triangle Mesh Compression” von Costa Touma und Craig
Gotsman wurde auf der ,,Graphics Interface ’98” zum ersten mal vorgestellt. Bei diesem
Verfahren handelt es sich, wie bereits zuvor beschrieben, um eine verlustfreie Komprimierung von 3D Gittermodellen. Der eigentliche Komprimierungsvorgang gliedert sich dabei
in zwei Schritte: Connectivity Encoding und Vertex Coordinate Compression.
3.1
Connectivity Encoding
Beim Connectivity Encoding werden alle Kanten des Gittermodells erfasst und dann in
Form von speziellen ,,Befehlen” kodiert. Als ergänzenden Schritt werden die resultierenden Befehle dann noch mit herkömmlichen Komprimierungsverfahren in ihrer Größe
reduziert.
Zum durchlaufen der Kanten wird zu Beginn der Komprimierung ein beliebiges Dreieck
des Modells ausgesucht. Einer der drei Eckpunkte dient als sogenannter ,,Focus Vertex”.
Das heißt, dass alle von diesem Punkt ausgehenden Kanten, nacheinander und im entgegengesetzten Uhrzeigersinn, durchlaufen werden. Die noch nicht durchlaufenen Kanten
des Focus Vertex werden als ,,Free Edge” bezeichnet.
Zusätzlich werden die drei Eckpunkte des, zu Beginn, gewählten Dreiecks in die ,,Active
List” übernommen. Beim weiteren Kodieren wird jeweils der Endpunkt der gerade kodierten Kante in diese Liste eingefügt. Knoten deren Kanten bereits alle kodiert wurden, werden wieder aus der Active List entfernt. Daraus ergibt sich, dass das Gittermodell durch
die Liste in zwei Hälften unterteilt wird: Ein innerer Teil, der alle bereits durchlaufenen
Kanten enthält, und ein äußerer Teil, der alle noch nicht besuchten Kanten enthält.
Der eigentliche Kodiervorgang beschränkt sich in der Mehrzahl der einzelnen Kodierungsschritte auf das erfassen der ,,Vertex degrees” mit dem sogennaten add-Befehl. Zur vollständigen Beschreibung des Gittermodells werden jedoch insgesamt 4 Befehle benötigt:
• add < degrees >
Hierbei wird der am anderen Ende, der zu kodierenden Kante, liegende Knoten betrachtet. Die Anzahl der von ihm ausgehenden Kanten (degrees) wird zusammen mit
dem Befehl ,,add (degrees)” gespeichert. So ergibt sich z.B. bei einem Knoten mit 6
abgehenden Kanten der Befehl ,,add 6”.
• add dummy < degrees >
Dieser Befehl hat im wesentlichen die selbe Funktionalität wie der normale addBefehl. Der einzige Unterschied besteht im Zusatz ,,dummy”. Verwendet wird dieser
Befehl immer dann, wenn das Gittermodell nicht rundherum geschlossen ist, also
z.B. Löcher in der Ober¤ äche hat. Um das Gittermodell fehlerfrei zu komprimieren
wird daher ein Dummy-Knoten in das Gittermodel eingefügt. Dieser Knoten wird
dann beim decodieren wieder entfernt.
• split < of f set >
Der split-Befehl wird verwendet, wenn der Endknoten, der als nächstes zu kodierenden Kante, bereits in der Active List enthalten ist (also bereits verarbeitet wurde).
In diesem Fall wird die Active List in zwei Teile unterteilt, wobei der eine Teil zur
späteren Bearbeitung auf einem Stack abgelegt wird und der andere Abschnitt direkt
weiter bearbeitet wird. Dabei gibt ,,offset” die Stelle an, an der die Liste geteilt wird.
Der offset-Wert entspricht der Anzahl der Knoten, die im Uhrzeigersinn entlang der
Active List durchlaufen werden, bis der Endknoten der neuen Kante erreicht ist. Der
5
Endknoten selber wird dabei mitgezählt. Also ergibt z.B. der Befehl ,,split 5” das die
Active List nach 5 Knoten, vom Focus Vertex ausgehend, geteilt wird. (Beispiel sh.
Abb. 1)
• merge < index >< of f set >
Wenn der Endknoten der zu kodierenden Kante bereits kodiert wurde und nicht in
der aktuellen Active List enthalten ist, muss er in einer der auf dem Stack liegenden
Listen enthalten sein. In diesem Fall wird der merge-Befehl verwendet. Der Befehl
enthält als Attribute einen index und einen offset. Der index enthält die Nummer, unter der die entsprechende Active List auf dem Stack liegt. Der offset hat eine ähnliche
Bedeutung wie beim split-Befehl: Der Wert entspricht der Anzahl der Knoten, die
im Uhrzeigersinn durchlaufen werden, bis der Endknoten der neuen Kante erreicht
ist. An dieser Stelle wird die aktuelle Active List mit der, auf dem Stack abgelegten,
Active List zu einer neuen Liste verbunden. (Beispiel sh. Abb. 2)
Nach dem alle Kanten des Gittermodells mit diesen Befehlen kodiert wurden, erhält man
eine Befehlsliste, die aus den 4 Befehlen besteht und z.B. folgende Form hat: add 6, add 5,
add 4, split 5, add 4.
Mit der Befehlsliste ist der erste Schritt des ,, Connectivity Encoding” beendet. Zur Verdeutlichung folgen in den nächsten 4 Abschnitten Flussdiagramme und Beispiele zum Encoding und Decoding.
6
Abbildung 1: Beispiel zum split-Befehl. Die gestrichelte Kante zwischen den beiden
Knoten soll kodiert werden. Da der Endknoten innerhalb der Active List (als schwarze
Linie dargestellt) liegt, werden zwei neue Active Lists erzeugt.
Abbildung 2: Beispiel zum merge-Befehl. Die gestrichelte Kante zwischen den beiden
Knoten soll kodiert werden. Da der Endknoten innerhalb einer anderen Active List liegt,
werden die beiden Active Lists zu einer gemeinsamen Liste verbunden.
7
3.1.1
Flussdiagramm Encoding
Abbildung 3: Flussdiagramm zum Encoding der ,,Mesh Connectivity”.
8
3.1.2
Beispiel Encoding
Abbildung 4: Beispiel zum Encoding der ,,Mesh Connectivity”. Die dicken Linien stellen
die Active List dar und die dicken Punkte den Focus Vertex. Gestrichelte Linien wurden
bereits kodiert. (a) Stellt das Gittermodell dar. (b) Da das Gittermodell nicht geschlossen
ist, wird ein Dummy-Knoten an den Eckpunkten eingefügt. (c) Das Ausgangsdreieck wird
festgelegt. So werden auch die ersten drei Befehle gewonnen: ,,add 6, add 7, add 4”. (d)
Im entgegengesetzten Uhrzeigersinn wird die nächste Kannte mit dem add-Befehl erfasst:
,,add 4”. (e) ,,add 8”. (f) ,,add 5” (Die Verbindungskante zum Dummy-Knoten wird mitgezählt). (g) ,,add 5” Damit sind alle freien Kanten des Focus Vertex bearbeitet. (h) Der
Focus Vertex wird entfernt und am nächsten Knoten der Active List entsteht der neue Focus
Vertex. (i) ,,add 4”. (j) ,,add 5”. (k) Der Endknoten der nächsten Kanten wurde bereits erfasst und liegt in der aktuellen Active List. Daher wird der split-Befehl angewendet. Dieser
Endknoten liegt auf der Active List 5 Knoten vom Focus Vertex entfernt. So ergibt sich der
Befehl: ,,split 5”. (l) Die Active List wurde in zwei Teile geteilt. Die innere Liste wird
auf dem Stack abgelegt. Der Endknoten der Kante wird zum Focus Vertex der äußeren
Active List. (m) ,,add 4”. (n) ,,add 4” Alle Kanten des Focus Vertex wurden bearbeitet. (o)
Der neue Focus Vertex hat nur noch eine freie Kante. Die Verbindungskante zum DummyKnoten: ,,add dummy 6”. Da keine weiteren freien Kanten entlang der Active List liegen
wird sie abgeschlossen. (p) Die nächste Active List wird vom Stack genommen. (q) ,,add
4”. (r) Verschieben des Focus Vertex. (s) Verschieben des Focus Vertex. Alle Knoten der
Active List sind erfasst. (t) Nachdem alle Kanten des Gittermodells kodiert wurden ergibt
sich folgende Befehlsliste: ,,add 6, add 7, add 4, add 4, add 8, add 5, add 5, add 4, add 5,
split 5, add 4, add 4, add dummy 6, add 4”.
9
3.1.3
Flussdiagramm Decoding
Abbildung 5: Flussdiagramm zum Decoding der ,,Mesh Connectivity”.
10
3.1.4
Beispiel Decoding
Abbildung 6: Beispiel zum Decoding der ,,Mesh Connectivity”. Ausgangspunkt ist die
beim Encoding gewonnene Befehlsliste: ,,add 6, add 7, add 4, add 4, add 8, add 5, add 5,
add 4, add 5, split 5, add 4, add 4, add dummy 6, add 4”. (a) Mit den ersten 3 Befehlen
,,add 6, add 7, add 4” und den entsprechenden Koordinaten wird das erste Dreieck erstellt.
Gleichzeitig wird die Active List erstellt und der Focus Vertex festegelegt. (b) ,,add 4”.
Ein neuer Knoten mit 4 Kanten wird erzeugt. die beiden inneren Kanten werden mit den
entsprechenden Knoten verbunden. (c) ,,add 8”. (d) ,, add 5”. (Die Kanten die später zum
Dummy-Knoten führen werden ebenfalls angelegt.) (e) ,,add 5”. Alle Kanten des Focus
Vertex wurden erzeugt. (f) Der Focus Vertex wird auf den nächsten Knoten der Active
List verschoben. (g) ,,add 4”. (h) ,,add 5”. (i) ,,split 5”. Durch den offset Wert 5 kann
der Endknoten der nächsten (dick gestrichelten) Kante bestimmt werden. (j) Durch den
split-Befehl wird die Active List geteilt. Die innere Liste wird auf dem Stack abgelegt. Der
Endknoten der neuen Kante wird zum Focus Vertex der aktuellen Active List. (k) ,,add 4”.
(l) ,,add 4”. Alle abgehenden Kanten des Focus Vertex wurden erzeugt. (m) Der Focus
Vertex wird verschoben. (n) ,,add dummy 6”. Die noch freien 6 Kanten werden mit dem
Dummy-Knoten verbunden. Damit sind alle Kanten der Active List wiederhergestellt. (o)
Die zweite Active List wird vom Stack genommen. (p) ,,add 4”. Alle abgehenden Kanten
des Focus Vertex wurden erzeugt. (q) Der Focus Vertex wird verschoben. Alle abgehenden
Kanten des Focus Vertex wurden bereits erzeugt. (r) Der Focus Vertex wird verschoben.
(s) Alle Kanten des Gittermodells wurden wiederhergestellt.
11
3.1.5
Komprimierung der Befehlsliste
Durch die Umwandlung der Kanteninformationen in eine Befehlsliste wird bereits eine
erhebliche Reduzierung der Datenmenge erreicht. Die Befehlsliste selber liegt jedoch noch
in einer unkomprimierten Form vor, so dass hier noch ein weiterer Komprimierungsschritt
erfolgen kann.
Wenn man die Befehlsliste aus dem Beispiel betrachtet, fällt auf, dass der add-Befehl mit
Abstand am häu£gsten verwendet wird. In typischen Gittermodellen verh ält es sich ähnlich: Neben dem add-Befehl gibt es nur noch einige wenige split-Befehle. Der mergeBefehl wird nur extrem selten verwendet.
Aus diesen Beobachtungen ergeben sich Komprimierungsverfahren deren Anwendung sich
sehr gut eignen: Lau¤ ängen- und Huffman-Kodierung. Besonders gute Ergebnisse werden
erzielt, wenn eine regelmäßige Struktur innerhalb des Gittermodells vorliegt. Dann lassen
sich Kompressionswerte von bis zu 0.2 Bits pro Knoten erreichen. Übliche Werte liegen
zwischen 3 und 0.2 Bits pro Knoten.
3.2
Vertex Coordinate Compression
Nachdem die Komprimierung der Kanteninformationen abgeschlossen ist, folgt die Komprimierung der Knotenkoordinaten.
Zu Beginn werden die Koordinaten quantisiert. Standartwerte für diese Quantisierung liegen zwischen 8 und 12 Bit. Dabei kann die Anzahl der Bits den Details des Gittermodells
angepasst werden: Eine höhere Anzahl an Bits für komplexe und aufwändig modellierte
Bereiche und niedrige Bitwerte für Regionen mit niedrigem Detailgrad.
Der nächste Schritt liegt in der Auswahl eines Anfangsdreiecks. Dieses Dreieck stimmt
üblicherweise mit dem Ausgangsdreieck des ,,Connectivity Encoding” überein. Ausgehend
von diesem Dreieck werden benachbarte Knotenkoordinaten bestimmt. Dabei wird die
Position des Knoten vorhergesagt und dann nur noch die Differenz zu den tatsächlichen
Koordinaten gespeichert.
Die Vorhersage der Knotenposition erfolgt mit Hilfe der sogenannten ,,Parallelogramm
Regel”. Hierbei wird der Knoten durch Bildung eines Parallelogramm aus einem Dreieck
erzeugt. Gegeben sind die 3 Vektoren des Dreiecks: z.B. ~u, ~v , w.
~ Der neue Punkt r~p wird
dabei mit folgender Formel berechnet:
~
r~p = ~v + ~u − w
Eine noch genauere Möglichkeit zur Koordinatenvorhersage erhält man, wenn man die
Winkel zwischen zwei oder mehreren benachbarten Dreiecken berücksichtigt. Dieses Verfahren wird auch als ,,crease-adapted prediction” bezeichnet. (Beispiel siehe Abb. 7)
Nachdem man alle Differenzwerte zwischen den originalen und vorhergesagten Koordinaten berechnet hat, können diese Werte noch, wie beim ,,Connectivity Encoding”, mit einem
Kompressionsverfahren wie z.B. Huffman komprimiert werden. Eine mögliche Alternative
hierzu ist das erstellen eines ,,Codebook” in dem die am häu£gsten vorkommenden Differenzwerte abgelegt werden. Gebräuchliche Größen für ein solches ,,Codebook” liegen
zwischen 16 und 128 Einträgen. Häu£g werden 32 Eintr äge verwendet.
12
Abbildung 7: ,,Parallelogramm Regel”. Aus dem Dreieck u, v, w wird mit Hilfe der
Parallelogramm Regel der Punkt rp bestimmt. Der Abstand zum ,,echten” Punkt r ist im
Vergleich zum Punkt rpc noch relative groß. Der Punkt rpc wird mit der ,,crease-adapted
prediction” ermittelt. Dabei wird der Winkel zwischen den beiden Dreiecken s, v, w und s,
t, v ermittelt und zur Erstellung des Punktes rpc verwendet.
13
4
Ergebnisse
Nachdem alle Komprimierungsschritte angewandt wurden, bleibt noch die Betrachtung der
erreichten Kompressionsraten. Die Tabelle 1 stellt einen Ausschnitt der, von den Autoren
des Verfahrens, erzielten Ergebnisse.
Bei den mit VRML97 gespeicherten Modellen ergibt sich ein Wert von 108 Bits pro Knoten, obwohl alle Modelle in einer komprimierten Form (gzipped) vorliegen.
Bei dem hier vorgestellten Verfahren ,,Triangle Mesh Compression” teilt sich das Ergebnis
in zwei Teilergebnisse auf. Beim ,,Connectivity Encoding” werden Raten von durchschnittlich 1,4 Bits pro Knoten erreicht, in Einzelfällen sogar bis zu 0,2 Bits. Etwas höher ist die
Datenmenge bei der ,,Vertex Coordinate Compression”. Hier liegen die Werte bei etwa 9
Bits pro Knoten. Aus den beiden Teilergebnissen ergibt sich eine durchschnittliche Kompressionsrate von 10,4 Bits pro Knoten.
Verglichen mit den VRML97 Modellen erreicht das vorgestellte Verfahren eine Datenmenge, die nur noch etwa ein zehntel so groß ist.
Model
Vertices
blob
triceratops
eight
shape
beethoven
engine
dumptruck
cow
Average
8036
2832
766
2562
2655
2164
11738
3066
Gzipped
VRML97
117K (119)
44K (127)
11K (118)
35K (112)
36K (111)
24K (91)
114K (80)
40K (108)
(108)
Triangle Mesh Compression
Conn.
Coord.
Total
1709 (1.7) 7951 (7.9)
(9.6)
764 (2.2)
2937 (8.3)
(10.5)
53 (0.6)
683 (7.1)
(7.7)
48 (0.2)
2990 (9.3)
(9.5)
781 (2.4)
3576 (10.8) (13.2)
330 (1.2)
3425 (12.0) (13.2)
1210 (0.8) 11162 (7.5) (8.3)
779 (2.0)
3376 (8.8)
(10.8)
(1.4)
(9.0)
(10.4)
Tabelle 1: Vergleich zwischen VRML97-Modellen (gzipped) und Modellen die mit Triangle Mesh Compression kodiert wurden. Die normalen Werte sind in Byte angegeben und
die Werte in Klammern geben die Anzahl von Bits pro Knoten an.
Abbildung 8: Beispiel für die in Tabelle 1 verwendeten Modelle beethoven und triceratops.
14
Literatur
[1] Gabriel Taubin, Jarek Rossignac, Geometric Compression Through Topological Surgery, ACM Transactions on Graphics, Vol.17, No.2, April 1998, pp. 84-115.
[2] Costa Touma, Craig Gotsman, Triangle Mesh Compression, Proc. of Graphics Interface 98, pp. 26-34, 1998.
[3] Stefan Gumhold, Real time compression of triangle mesh connectivity. In Siggraph98
Conference Proceedings, pp. 133140, July 1998.
[4] Jarek Rossignac, Edgebreaker: Connectivity compression for triangle meshes, IEEE
Transactions on Visualization and Computer Graphics, 5(1), 1999.
15
Herunterladen