Beiträge von Tale-X im Thema „3D-Grafik in V2 BASIC“

    Ich meinte schon hatformel2.prg ;) - sehe gerade, dass steht noch auf der ersten Seite - das hat noch nicht die beiden großen Arrays (l() und p()) drin. Das sollte auf jeden Fall funktionieren.

    Den Screenshots nach sind die kompilierten Programme größer bzw. weiter hin im Speicher. Die "Wellen" im Screenshot vom Austro kenne ich auch von meinen Experimenten - das sind die Arrays. Beim anderen Screenshot würde ich pauschal tippen, dass im Bildschirmspeicher der Programmcode zu sehen ist.

    Was passiert genau - stürzt es ab, ist die Grafik Müll?

    Ich würde pauschal vermuten, dass die Arrays bei den letzten Fassungen das Problem sind, der verfügbare Basicspeicher ist da ziemlich aufgebraucht. Versuch mal die Fassung hatformel2.prg von weiter oben. Wenn die geht, könnte man da mit dem Kosinusersatz rangehen und das dann durch den Compiler jagen.

    So, ich hatte jetzt im ersten Anlauf den Faktor cf zu r "hochgezogen", hab allerding auch nen kleinen Bock eingebaut

    Code
    20 forx=.toxp:r=sqr(x*x/sf+yq/vz)/cf 
    190 def fnc(x)=cv(n5+(xandby))


    Der Code wurde dadurch etwas schneller - 17:45

    Nachdem ich n5 entfernt habe war die Formel so kurz, dass ich sie in die Hauptfunktion eingesetzt habe (p(y,x)=... ist jetzt in der nächsten Zeile). Eine weitere Optimierung betrifft Zeile 20: Der Umrechnungsfaktor cf ist konstant, genauso wie sf und vz - kann ich also gleich in sf und vz einrechnen (beide werden auch nirgendwo anders verwendet). Dadurch kein Mehraufwand mehr in der Schleife für das Umrechnung 2pi->512!

    Code
    ...
    7 m7=504:e4=40:cf=2*./512:by=511
    8 yl=200:n1=-1:n5=.5:nh=900:eh=100:hs=160:sf=3136*cf*cf:vz=196*cf*cf:s=1:a=7872
    ...
    20 forx=.toxp:r=sqr(x*x/sf+yq/vz)
    21 f=cv(randby)-cv((3*r)andby)/3+cv((5*r)andby)/5-cv((7*r)andby)/7
    22 p(y,x)=int(e4*f+n5):fl=.:xp=hs+x-y:yp=eh+y+y-p(y,x)
    ...
    190 rem entfaellt

    Aktuelle Durchlaufzeit: 16:46

    So, und nochmal eine funktionierende Beschleunigung, allerdings zu Lasten der Bildqualität. Diesmal baue ich zu Anfang eine Wertetabelle mit 512 Einträgen, die den Bereich von 0 bis 2pi abdeckt - alles was außerhalb des Bereichs liegt, kann darauf zurückgerechnet werden ((Wert*512)/(2*pi))AND511.
    Hinzufügte Variablen:
    cv(512) - Array für Zwischenwerte
    cf - Umrechnungsfaktor Winkelfunktion -> Array (2pi/512)
    ct - Temporäre Variable beim Befüllen des Arrays
    by - Wert 511 (für AND-Verknüpfung)

    Zur Initialisierung wird in Zeile 10 das Unterprogramm ab Zeile 100 aufgerufen. Dort wird die Wertetabelle befüllt und die FNC-Funktion definiert (DEF FNC(x)...). Die FNC-Funktion wird dann in der Hauptfunktion (Zeile 21) statt der COS-Funktion verwendet.

    Code
    100 fort=0to128
    130 ct=cos(t*cf)
    140 cv(t)=ct
    150 cv(512-t)=ct
    160 cv(256-t)=-ct
    170 cv(256+t)=-ct
    180 next
    190 def fnc(x)=cv((n5+x/cf)andby)
    200 return

    Ergebnis: 18:28 (statt ursprünglich >50 Minuten)

    Wenn n5 aus Zeile 190 rausgenommen wird, ist's knapp über 18 Minuten (allerdings mit etwas ausgefransteren Kurven). Durch Auflösen der FNC-Aufrufe in der Hauptfunktion (f=fnc(r)-fnc(3*r)/3...) lässt sich sicherlich die Zeit noch auf unter 18 Minuten drücken. Ich hab' jetzt aber erst mal genug von Hüten ;)

    Nachtrag: die Wertetabelle für die Cosinus-Werte definiere ich NACH dem Array das den Grafikspeicher überbrückt, ansonsten ragt sie in den Grafikbereich rein. Außerdem musste ich das Grafikspeicher-Array verkleinern - sonst out of memory (endlich hab' ich ein Programm geschrieben, dass den ganzen Speicher nutzt :thumbsup: ). Auch der Code darf nicht zu lang werden, sonst ragt was in die Grafik rein...

    Danke... ich hoffe, dass mir auch produktive Dinge noch einfallen.

    @HexWorks: worum geht es bei Print2Bitmap?

    So, ich bin jetzt bei 20:43 und damit vermutlich am Ende der Möglichkeiten (lass mich aber gerne vom Gegenteil überzeugen, vor allem, wenn jemand die Kosinusreihe "entschärft" bekommt).

    Was gibt's zu sagen - Kosinus und Quadrat sei dank kann ich auch in y-Richtung die Hälfte der Berechnungen einsparen, muss hier die Werte merken.

    Problem:
    Beim Füllen des Arrays mit den Werten werden diese fröhlich in den Grafikspeicher geschrieben (deja vu? ;) )

    Lösung:
    Ein Leerarray vorneweg das dafür sorgt, dass die Werte im Speicher hinter der Grafik liegen. Bekannter Warnhinweis - danach keine neuen Variablen einfügen (bzw. nicht nach dem ersten Pixel).

    Damit das Leerarray nicht ganz unnütz ist, lege ich dort die Speicheradressen der Zeilen für die Grafikroutine ab (ersetzt li) - diesmal für alle 200 y-Werte. Beim Wechsel in die zweite Hälfte wird die Bildschirmrahmenfarbe gewechselt und er greift nur noch auf die zwischengespeicherten Ergebnisse zu

    Danke *verneig* Das Basic vom C64 ist nicht zu verachten - welches Basic hat so einen mächtigen Befehl, der sämtliche Grafik- und Soundbereiche abdeckt :bgdev

    Ich weiß nicht, ob ich's schreiben soll, aber ich bin jetzt beim Hut bei 21:56 Minuten Laufzeit... in Basic :whistling:

    Der Hut verleitet zum Experimentieren - ich habe jetzt die Berechnungen als nächstes Optimierungsziel entdeckt:

    Code
    (restlicher Code)
    8 yl=200:n1=-1:n5=.5:z=0:nh=900:eh=100:hs=160:sf=56:vz=14:e=1
    (restlicher Code)
    19 fory=30to-30stepn1:xp=int(z4*sqr(nh-y*y)+n5)
    20 forx=-xptoxp:xr=x/sf:yr=y/vz:r=sqr(xr*xr+yr*yr)
    (restlicher Code)


    Mal etwas umstellen:

    Code
    r=sqr(xr*xr+yr*yr)
    r=sqr((x/sf)*(x/sf)+(y/vz)*(y/vz))
    r=sqr((x*x)/(sf*sf))+(y*y)/(vz*vz))


    sf und vz sind Konstanten, die nur an dieser Stelle verwendet werden, so dass vz*vz und sf*sf schon vorher berechnet werden kann. Eine weitere Abkürzung: die Teilberechnung y*y findet sich auch in Zeile 19 wieder. xr und yr entfallen ersatzlos. Die geänderten Codezeilen lauten dann:

    Code
    (restlicher Code)
    6 dimbi(7),li(24),ad,yq
    (restlicher Code)
    8 yl=200:n1=-1:n5=.5:z=0:nh=900:eh=100:hs=160:sf=3136:vz=196:e=1
    (restlicher Code)
    19 fory=30to-30stepn1:yq=y*y:xp=int(4*sqr(nh-yq)+n5)
    20 forx=-xptoxp:r=sqr(x*x/sf+yq/vz)
    (restlicher Code)


    Ergebnis: statt 53:17 jetzt 52:01. Mit weiteren Optimierungen (Streichen von z1 bis z9, Arraydefinition nach hinten schieben) lande ich bei 51:09 und der Code sieht wie folgt aus:


    Dauer org 56:23
    Dauer neu 51:10
    ->5:10 Minuten Ersparnis (9%)Ist doch schon mal was, oder?

    Okay, nicht berauschend, also weiterschauen:
    Die einzelnen Kurven sind axialsymmetrisch (Kosinus ftw!) und gehen immer von -x bis +x - warum berechnen wir dann die Werte doppelt? Also mal fix das Programm umgestrickt, dass wir gleichzeitig von links und rechts zeichnen (rechts ab Zeile 26), dann reicht bei x auch der halbe Wertebereich:


    Laufzeit jetzt: 30:08 (gegenüber Urfassung eine Einsparung von 26:15 Minuten -> 46% Einsparung). Das bringt was! :)

    Inspiriert hat mich dazu übrigens der KC85/3 mit seiner Kreiszeichenroutine (8 Punkte gleichzeitig) - das war sichtlich effizienter als das was Simons Basic malte...

    Und nu viel Spaß beim knacken der 30:00er Marke - im Array- statt Poke-Thread gibt's einen Tipp dafür.

    Frohes Experimentieren (und nicht immer nur auf den Code schauen! ;) )
    Tale-X

    Ah gut, hab's verstanden, gut auch der Hinweis mit dem Gosub. Die im Laufe der Zeit entstandenen (Wissens)lücken schließen sich langsam wieder.

    Oder wenn ein FOR die gleiche Laufvariable verwendet, werden etwaige bereits offenen FOR-NEXT-Schleifen (und alle darin verschachtelten) vom BASIC-Stack entfernt. Schaut mitunter wild aus - im Forum war in jüngerer Zeit eh so ein Listing nur mit gleicher Schleifenvariable mit an allen Ecken und Enden offenen Schleifen ...

    In den 80ern wurde man für sowas geteert und gefedert. Eigentlich eine gute Tradition... :bgdev

    Hi,

    ich glaube nicht, dass der Hut nur einmal gezeichnet wurde ;) ich hatte ihn mehrfach durchlaufen lassen und verschiedene "Optimierungs"variationen probiert. Z.B. wie sich die Verwendung von Integer-Variablen statt normaler Variablen auf die Laufzeit auswirkt oder ob ich via Print den Farbbildschirm schneller gesetzt bekomme als mit Poke. Der Hut ist durch seine kompakte Programmgröße und lange Laufzeit ideal dafür geeignet.

    Die Verwendung von Konstanten statt Zahlen hatte bei meiner Zeichenroutine übrigens schon den einen oder anderen Geschwindigkeitspunkt (oder besser Pünktchen) gebracht. Allerdings macht die Grafikausgabe nur ca. 10% der Laufzeit aus (hatte ich auch mal getestet). Die Einsparbrocken sind also woanders zu suchen. Dank Deiner Beschreibungen hab' ich wieder paar neue Ideen... :)

    Kleine Frage zur Codezeile: das Next dort wird nur dann ausgeführt, wenn die Then-Bedingung erfüllt ist? Dann müsste ja dann noch ein Next für den "Else"-Fall stehen. Wie stellst Du da sicher, dass ein zweites Next für die I-Schleife nicht zu einem Fehler führt (falls er im IF-Teil die I-Schleife komplett durchläuft)? Mir ist da keine saubere bzw. nicht umständlich aussehende Lösung eingefallen.

    Viele Grüße
    Tale-X