Im vorangegangenen Artikel, der zusammen mit dem Programmlisting als einzelner Artikel gerade noch vertretbar schien, wurde ein Programm zur Erstellung und Darstellung dreidimensionaler Objektgrafik vorgestellt. Einige Fragen, die noch offenbleiben muhten sowie einige hilfreiche Funktionen zur Programmerweiterung werden jetzt hier behandelt.
GFA-Freaks werden es schon längst erkannt haben, die Datenstruktur des Felds Xyz%(2,Pun_anz) für die Punkte weicht von der des Flächenfelds Fl%(Eck_max+3,Fl_max) ab. So werden die Punkte von 1 bis P_anz durchnumeriert im Gegensatz zu den Flächen, die von 0 bis F_anz-1 zählen. Die Einträge im Punktfeld entsprechen den Koordinaten X,Y,Z des jeweiligen Punkts. Die Einträge im Flächenfeld von 0 bis Eck_max sind die Nummern der Punkte analog zum Feld Xys%() in der ‘Korkenzieherreihenfolge’. Die drei Einträge, die darauf folgen (Eck_max+1 bis Eck_max+3) sind zuerst die Anzahl der Punkte - 1 und dann 2 Werte für die Farb- oder Musterinformation.
Mit Kenntnis dieser Struktur erschließt sich einem die hier neu vorgestellte Prozedur F use recht gut. Am linken Rand des Bildschirms werden alle vorhandenen Flächen aufgelistet. Sollten es mehr sein als der Monitor anzeigen kann, läßt sich mit Pfeilen nach oben oder nach unten scrollen. Jeder Kasten zeigt Füllfarbe oder -muster, die Flächennummer und die Anzahl der Punkte dieser Fläche Eine Mausbewegung auf einen der Kästchen, und eine Inrandung (neudeutsch: Gegensatz von Umrandung) erscheint. Zudem blinken die Punkte dieser Fläche im Anzeigefeld, falls sie sichtbar sind. Ein Mausklick auf das Flächenkästchen, und es erscheint eine Alarmbox mit den Möglichkeiten. Füllmuster oder -farbe abzuändern oder die Fläche wegzuwerfen. So lassen sich nun falsch konstruierte Flächen leicht entfernen, und die Umwandlung von Objekten verschiedener Auflösungsstufen ist auch schnell gemacht.
Geradezu notwendigen Komfort bringen die neuen Menüpunkte “OBJ LADEN" und “SPEICHERN". Nomen est Omen, es sollte nur erwähnt werden, daß mit Rechtsklick auf diese Menüpunkte ein Pfadname vorgegeben werden kann, und die Dateiart *.3D? sollte am besten à la DEGAS für die unterschiedlichen Auflösungsarten verwendet werden (3D1 niedrige Auflösung, 3D2 mittel, 3D3 hochauflösend).
Die Dateien werden nach einem einfachen Verfahren zusammengequetscht, man muß jedoch darauf achten, daß die Variable Eck_max nicht kleiner gewählt wird als die maximale Eckenzahl des zu ladenden Objekts, sonst erfolgt eine Warnung vom Programm. In diesem Zusammenhang der Hinweis, daß die Variablen Pun_max (maximale Punktanzahl), Fl_max (maximale Flächenanzahl) und Eck_max (maximale Anzahl der Eckpunkte einer Fläche) je nach Belieben verändert werden können.
Eine neue Funktion ist auch "TIEFENVERZERRUNG". Hiermit können die Grundwerte von Darstx und Darsty verändert werden, die die Anzeige der Tiefe im Eingabefenster regeln. Dies ist vor allem dann vonnöten, wenn mehrere Punkte so dicht beieinanderliegen, daß die Flächenerstellung zur Tortur wird. Nach einem Klick auf “TIEFENVERZERRUNG" verändert sich die Darstellung abhängig von der Mausposition. Sie sollte langsam von der oberen rechten Ecke des ersten Quadranten Richtung Ursprung geändert werden. Je näher man dem Mittelpunkt kommt, desto stärker die Verzerrung. Bei der Position, an der die Punktauflösung günstig ist, genügt ein Mausklick, und die neue Verzerrung wird von nun an vom Programm verwendet.
Kaum erwähnenswert ist die Programmabbruchsfunktion, die einem die Fingerakrobatik von Alternate-Shift-Control erspart. Bei Programmversionen, die man kompilieren will, sollte “End" durch “Quit" ersetzt werden.
Eine weitere Änderung ergibt sich in der Angabe der X-, Y-, Z-Werte. Die X- und Y-Koodinate können jetzt genau wie der Z-Wert mit Mausdruck oder -klick verändert werden. Damit verschiebt sich das Koordinatenkreuz, und Objekte, die größer sind als das Eingabefenster, können bearbeitet werden.
Die letzte Veränderung bezieht sich auf die neue Menüfunktion “QUADER ERSTELLEN". Hiermit kann ein beliebig großer Quader an jeder Stelle parallel zu den Koordinatenachsen erstellt werden. Nach Klick auf die Menüfunktion muß man sich zuerst entscheiden, ob man den Quader anhand des Mittelpunkts oder des vorderen linken unteren Eckpunkts bestimmen will. Danach können die Größenangaben für drei Seiten angegeben werden, und dann erfolgt die Eingabe des Eckpunkts bzw. des Mittelpunkts. Nun brauchen nur noch die 6 Muster oder Farben für die Flächen des Quaders eingegeben zu werden, und er erscheint in dem Anzeigefeld.
In der bisherigen Programmbeschreibung wurden zwei Funktionen über die das Programm verfügt, nicht erläutert. Die eine bezieht sich auf das selbsttätige Überprüfen der 'Korkenzieherregel' bei der Flächenerstellung. Bei allen exakt definierten ausgefüllten Objekten gehört jede Linie zu genau 2 Flächen. Und bei konsequenter Anwendung der ‘Korkenzieherregel' stellt sich heraus, daß die Flächenecken jede Linie immer gegenläufig beschreiben. Abbildung 1 veranschaulicht diesen verbal schwer zu beschreibenden Effekt. Hier setzt auch das Programm ein und überprüft in der Prozedur F_akt, ob nach Fertigstellung einer Fläche diese mit irgendeiner Linie einer anderen Fläche dieselbe Richtung beschreibt. Falls ja, werden die Eckpunkte in umgekehrter Reihenfolge abgespeichert (unter Zuhilfenahme des X%()-Feldes). Dies erklärt, warum neue Flächen immer an bereits existierende angrenzen sollten, denn nur dann kann das Programm die richtige ‘Korkenzieherorientierung' überprüfen bzw. einsetzen.
Ein anderer Aspekt ist die Darstellung des Objekts mit den den Linienmustern innewohnenden Angaben über Flächenzugehörigkeit. Dieser für die Erstellung vollständiger Objekte hilfreiche Modus, der sich mit “INFO + ANZEIGE" umschalten läßt, wird durch die Überprüfung in der Prozedur “Show" (If Grmbo...) erreicht. Hier wird jede Linie daraufhin überprüft, ob sie bei einer anderen Fläche auch schon vorhanden ist und, falls ja, gestrichelt dargestellt. Diese Überprüfung geht (Brute Force) alle Flächen und deren Linien durch und bricht nur bei einer zweiten Linie ab. Dieser Aufwand, der für jede einzelne Linie aufgebracht werden muß. erklärt den langsamen Bildaufbau in dieser Darstellungsart. Programmtechnisch kann hier noch viel verbessert werden. da jede gestrichelte Linie ja mindestens zweimal berechnet und ausgegeben wird. Um das Programm nicht noch länger und unübersichtlich zu machen, mußte hierauf leider verzichtet werden.
Ein Hinweis noch für die Erstellung von großen Flächen mit vielen Eckpunkten. Hier muß darauf geachtet werden, mit den ersten drei Punkten ‘Korkenzieherrichtigkeit' zu erzielen, denn nur diese werden für die Berechnung des Kreuzprodukts ausgewertet. Danach entgegengesetzte Laufrichtung beeinflußt die Darstellung nicht im mindesten.
Die Einbindung der neuen Prozeduren dürfte nicht schwerfallen. Außer den DATA-Zeilen muß nur noch der Befehlsaufruf in der Hauptschleife ersetzt werden (siehe Listing). Die Prozeduren selbst können einfach an das bisherige Programm angehängt werden. Und nach all der Mühe bleibt lediglich noch der Wunsch, daß sie mit beeindruckenden 3D-Konstruktionen und erfolgreichen Programmerweiterungen gekrönt werden. Die Redaktion würde sich freuen, an Ihren Erfahrungen und Ergebnissen teilzuhaben.
Martin A. Wielebinski
Literatur
William M. Newman/Robert F. Sproull,
Grundzüge der interaktiven Computergrafik,
1986, McGraw-Hill, Hamburg
c't 1984,
Heise Verlag, Hannover
(Sehr unterhaltsame Artikelserie über ein 6502-Assemblerpaket für dreidimensionale Drahtmodelle.)
c't S.144 ff
Von Vektoren und Volumina: Nr. 2 1988,
Heise Verlag, Hannover
CHIP SPECIAL
Computergrafik: März 1981,
Vogel Verlag, Würzburg.
'
' *************************************************
' * *
' * 3D-Grafik Edier- und Demoprogramme für die ST *
' * von Martin A Wielebinski. *
' * Teil 2, die bisher 'reservierten' Funktionen: *
' * Flächeneditor, Load & Save. *
' * *
' *************************************************
'
' Um die zusätzlichen Prozeduren lauffähig zu machen müssen zwei kleine
' Änderungen des Originalprogramms vorgenommen werden
'
' Die Befehlsaufrufe in der Hauptschleife lauten nunmehr:
'
If Com<10
On Com Gosub Wert,Wert,Wert,In_gr,Verz,Gitt,Phol,Fhol,G3d
Else
On Com-9 Gosub F_use,Quader,D,D,D.D,D,D,Olad,Osp,Pstp
Endif
'
' Und die Data-Zeilen mit dan Menütasten folgendermaßen:
'
Data "- X: +"
Data "- Y: +"
Data "- Z: +""
Data INFO + ANZEIGEMODUS
Data TIEFEN-VERZERRUNG
Data GITTER | SETZEN
Data PUNKTMOD|XYZ-EING
Data FLÄCHEN ERSTELLEN
Data 3D-GRAFIK STARTEN
Data FLÄCHEN EDITIEREN
Data QUADER EINGEBEN
Data FREI,FREI,FREI
Data FREI,FREI,FREI
Data OBJ LADEN|PFAD BEST
Data SPEICHERN|PFAD BEST
Data 3D PROGRAMM BEENDEN
'
' Die nun folgenden Prozeduren werden einfach an das Originalprogramm
' angehängt, eigene Funktionen müsstan problemlos
' weiterbenützt werden können.
'
Procedure Verz ! Bildschirmverzerrung einstellen
Local I,J,A$
A$="Darstellungsverzerrung:|Je näher sie die Maus dem|Mittelpunkt bringen"
Gosub Ali(0,A$+' desto|stärker die Verzerrung.",1,"Aha!")
Gosub Mclr
J=Grmbo ! Schnelle Darstellung
Grmbo=0
Repeat
Darstx=(Mousex-Ymi)/10 ! Verzerrung x und y anhand
Darsty=(Ymi-Mousey)/10 ! des Mittelpunkts berechnen
If Darstx=0 ! Dürfen aber nicht 0 betragen
Darstx=1
Endif
If Darsty=0 ! dito
Darsty=1
Endif
Gosub Show ! Veränderungen anzeigen
Until Mousek ! bis Maustaste geklickt wird
Grmbo=J ! Originaldarstellung wieder herstellen
Return
'
Procedure Hol_pfad ! Kein Kommentar
Gosub Inbox("DEN ZUGRIFFSPFAD FÜR|DIE DATEN ANGEBEN.|z.B: A:\GFA\GRAFIK\3D\",1)
Disk$=Wert$
Return
''
Procedure Osp ! Objekt abspeichern
Local I,J,Maxeck
If Mk=2
Gosub Hol_pfad ! Bei Rechtsklick Pfad holen
Else ! sonst:
Fileselect Disk$+"*.3D?",F$
If F$<>""
Open "O",#1,F$ ! Falls guter Dateiname öffnen
Maxeck=0
For I=0 To F_anz-1
If Fl%(Eck_max+1,I)>Maxeck
Maxeck=Fl%(Eck_max+1,I) ! Maximale Eckanzahl einer Fläche des
Endif ! Objekts ermitteln
Next I
Gosub Byte(F_anz) ! Punktanzahl,
Gosub Byte(F_anz) ! Flächenanzahl
Gosub Byte(Maxeck) ! und maximale Eckenanzahl zur Datai
If P_anz
For I=1 To P_anz
For J=0 To 2
Gosub Byte(Xyz%(J,I)) ! Alle Punktkoordinaten,
Next J
Next I
Endif
If F_anz
For I=0 To F_anz-1
For J=0 To Maxeck
Gosub Byte(Fl%(J,I))! alle relevanten Flächennummern
Next J
For J=Eck_max+1 To Eck_max+3
Gosub Byte(Fl%(J,I))! und die Flächeninformationen ausgeben.
Next J
Next I
Endif
Close #1 ! Das war es schon.
Endif
Endif
Return
'
Procedure Byte(W) ! Diese Proz. wirft 2 Bytes zur Diskette
W=W+32768
Out #1,(W Div 256)
Out #1,(W Mod 256)
Return
'
Procedure Olad ! Lädt ein Objekt von Disk
Local I,J,Maxeck
If Mk=2
Gosub Hol_pfad ! Rechtsklick -> holt Pfad
Else
Fileselect Disk$+"*.3D?","",F$
If F3<>""
Open "I",#1,F$ ! Falls guter Dateiname anfügan
Gosub Wrd
I=Ww ! und 3 Words einlesen
Gosub Wrd
J=Ww
Gosub Wrd
Maxeck=Ww
If Maxeck>Eck_max ! Maximale Eckanzahl möglich?
Gosub Ali(3,"Objekt hat mehr Ecken|als die Var. Eck_max.",1,"Stop")
Else
P_anz=I ! JA, Werte übernehmen
F_anz=J
If P_anz
For I=1 To P_anz
For J=0 To 2
Gosub Wrd
Xyz%(J,I)=Ww ! Alle Punktkoordinaten
Next J
Next I
Endif
If F_anz
For I=0 To F_anz-1
For J=0 To Maxeck
Gosub Wrd
Fl%(J,I)=Ww ! alle Flächennummern
Next J
For J=Eck_max+1 To Eck_max+3
Gosub Wrd
Fl%(J,I)=Ww ! und alle Flächeninfos lesen.
Next J
Next I
Endif
Endif
Close #1 ! das wars...
Endif
Endif
Return
'
Procedure Wrd ! Diese Procedure liest 2 Bytes
Wl=Inp(#1)
Ww=Wl*256+Inp(#1)-32768
Return
'
Procedure Pstp ! Programm abbrechen???
Local A$
A$="Programm wirklich|beenden und alle|Daten vernichten?"
Gosub Ali(3,A$,2," JA |Nein")
If But=1
Cls ! Jawoll!!!
End
Endif
Return
'
' Diese umfangreiche Procedure ermöglicht die Edierung von Flächen:
'
Procedure F_use
Local Mmx,Mmy,Mmk,I,Stnr,Aktnr,Rnr,A$
If F_anz
A$="Sie können links die Fläche|auswählen und durch|Mausklick edieren!"
Gosub Ali(0,A$+"Zurück mit Rechtsklick!",1,"Aha!")
Deffill 0,1
Pbox 0,0,50,Ysl
Text 10,Tyo,"^^^^^"
Text 10,Yty*19+Tyo,"vvvvv" ! Bildschirm ruinieren
Color 1
Stnr=0 ! Startnummer = 0
'
Starty:
Deffill 0,1
Pbox 0,Yty,50,Yty*19 ! Flächenbox am linken Schirmrand
Aktnr=-1
For I=1 To 18
Box 0,Yty*I,50,Yty*(I+1) ! Box ausgeben
If Stnr+I-1<F_anz
A$=Str$(Stnr+I)+" "+Str$(Fl%(Eck_max+1,Stnr+I-1)+1)+"P"
Text 28-3*Len(A$),Yty*I+Tyo,A$ ! Text ausgeben
Mmy=Fl%(Eck_max+2,Stnr+I-1)
Mmx=Fl%(Eck_max+3,Stnr+I-1)
If Max
Deffill 1,Mmx,Mmy
Else
Deffill Mmy,1
Endif
Pbox 0,Yty*I,8,Yty*(I+1) ! Füllfarbe oder -muster
Endif
Next I
Do ! Warteschleife
Mouse Mmx,May,Mak
If Mmx<40 ! Maus In Box?
I=Mmy Div Yty
If I>0 And I<19 And Stnr+I-1<F_anz ! ja, gültige Flächennummer?
If I<>Aktnr
Graphmode 3 ! ja, aktivieren
If Aktnr<>I ! alte ausschalten???
Box 10,Yty*Aktnr+2,48,Yty*(Aktnr+1)-2 ! jawoll
Endif
Box 10,Yty*I+2,48,Yty*(I+1)-2 ! Inrandung
Aktnr=I ! aktive Position
Rnr=Stnr+Aktnr-1 ! aktuelle Flächennummer
Graphmode 0
Endif
Endif
If Mmk=1 ! Maus auch noch gedrückt?
If I>0 And I<19 ! ja, auf Flächennummer?
If Aktnr<>-1
Gosub Ali(2,"Fläche löschen oder|neu einfärben ???",1,"Mix|Kill|Farbe")
If But=3
Gosub Colget ! neue Farbe oder Muster holen
Fl%(Eck_max+2,Rnr)=Cnr !abspeichern
Fl%(Eck_max+3,Rnr)=Czei
Endif
If But=2 And F_anz>0 !Fläche löschen???
For I=Rnr To F_anz !jawoll, durch Verschieben
For J=0 To Eck_max+3 ! hinauswerfen
Fl%(J,I)=Fl%(J,I+1)
Next J
Next I
Dec F_anz ! Flächenzähler -= 1
Endif
Endif
Goto Starty ! und neue Box zeichnen..
Else
If I=0 ! Nach oben scrollen?
Sub Stnr,16
If Stnr<0
Stnr=0
Endif
Goto Starty
Else
Add Stnr,16 ! ansonsten nach unten
If Stnr+16>F_anz
Stnr=F_anz-18
Endif
Goto Starty
Endif
Endif
Endif
Endif
If Aktnr<>-1 ! Falls Fläche gewählt
Gosub Flacker(Stnr+Aktnr-1) ! Die Punkte blinken
Gosub Flacker(Stnr+Aktnr-1) ! lassen
Endif
Exit If Mmk=2 ! Bei Rechtsklick beenden
Loop
Endif
Return
'
Procedure Flacker(F_nr) ! Punktblinkroutine
Local I,J,X,Y
Graphmode 3
For J=0 To Fl%(Eck_max+1,F_nr) ! Alle Punkte
I=Fl%(J,F_nr) ! umrechnen
X=Ymi-Arbxyz%(0)+(Xyz%(0,I)+(Xyz%(2,I)-Arbxyz%(2))/Darstx)
Y=Ymi-Arbxyz%(1)-(Xyz%(1,1)+(Xyz%(2,I)-Arbxyz%(2))/Darsty)
Xf X>53 And X<Ys-3 ! und falls sichtbar
Circle X,Y,4 ! anzeigen
Endif
Next J
Graphmode 0
Return
'
Procedure Quader ! Quader in einem Zug erstellen
Local P1,P2,P3,P4,P5,P6,F7,P8,I,Bo,A$
A$="Quader erstellen. Wodurch|festlegen? (Mitte oder|Ecke unten links vorne)"
Gosub Ali(2,A$,1,"Nix|Mitte|Ecke")
If But>1
Gosub Inbox("LÄNGE DER X,YZ-SEITEN|EINGEBEN.",3)
Bo=1
For I=0 To 2
Y%(I)=X%(I) ! Werte merken
If Y%(I)=0
Bo=0 ! Falls 0 abbrechen
Endif
Next I
If Bo
Gosub Inbox("UND JETZT DEN BE-|FESTIGUNGSPUNKT ",3)
If But=2 ! Falls Mittelpunkt
For I=0 To 2
X%(I)=X%(I)-Y%(I)/2 ! Un.li vor Ecke errechnen
Next I
Endif
Gosub P_neu(X%(0),X%(1),X%(2)) ! Alle neuen Punkte anfordern
P1=Pnr
Gosub P_neu(X%(0),X%(1)+Y%(1),X%(2))
P2=Pnr
Gosub P_neu(X%(0)+Y%(0),X%(1)+Y%(1),X%(2))
P3=Pnr
Gosub P_neu(X%(0)+Y%(0),X%(1),X%(2))
P4=Pnr
Gosub P_neu(X%(0),X%(1),X%(2)+Y%(2))
P5=Pnr
Gosub P_neu(X%(0),X%(1)+Y%(1),X%(2)+Y%(2))
P6=Pnr
Gosub P_neu(X%(0)+Y%(0),X%(1)+Y%(1),X%(2)+Y%(2))
P7=Pnr
Gosub P_neu(X%(0)+Y%(0),X%(1),X%(2)+Y%(2))
P8=Pnr
Gosub F14_neu(P1,P2,P3,P4) ! und die 6 Flächen erstellen
Gosub F14_neu(P1,P5,P6,P2)
Gosub F14_neu(P2,P6,P7,P3)
Gosub F14_neu(P3,P7,P8,P4)
Gosub F14_neu(P4.P8,P5,P1)
Gosub F14_neu(P8,P7,F6,P5)
Endif
Endif
Return
'
Procedure F14_neu(A,B,C.D) ! 4-Punktfläche erstellen
Fl%(0,F_anz)=A
Fl%(1,F_anz)=B
Fl%(2,F_anz)=C
Fl%(3,F_anz)=D
Fl%(Eck_max+1,F_anz)=3 ! alles eintragen
Gosub Colgat ! Farbe oder Muster holen
Fl%(Eck_max+2,F_anz)=Cnr ! abspeichern
Fl%(Eck_max+3,F_anz)=Czei
Inc F_anz ! Flächenzähler erhöhen
Return
Listing: 3 D-Grafik-Edier- und Demoprogramm Teil 2