Deutsch
PHP, HTML & JavaScript- Forum

3D Grafik - WebGL mit three.js

 
- Seite 1 -



HofK
Auf einen heißen Tipp von IF hin, habe ich mir mal
three.js  [...]  angeschaut. Da  [...]  (ganz unten) die ersten Resultate.
 
31.01.2016  
 



 
- Seite 39 -



HofK
Die Zuordnung der 8 Bit Maschinenbefehle zu den Assembler-Mnemonics und den Operanden ist eine recht umfangreiche XProfan Prozedur.

proc assembler_to_binary_code ' Assembler --> Binärcode

Ich habe sie zwar einfach in mein Javascript kopieren können, aber dann geht die Arbeit erst richtig los.

Bei der Entwicklung der "höheren" Programmiersprachen in den letzten mehr als 60 Jahren, sind die Autoren nicht sehr einheitlich vorgegangen. Zwar ist das Vokabular ( bzw. die Abkürzungen ) in der Regel der englischen Sprache entnommen, aber für eine Sache werden trotzdem verschiedene Bezeichner benutzt. Und dann die unterschiedlichen Trennzeichen und Klammerungen. Da kann man leicht den Überblick verlieren.

Aus
select mn$
...
endselect

wird
switch( mn$ ) {
...
}


und die Fälle ändern sich von z.B.
caseof "NOP"
zu
case "NOP":

Macht man aus caseof per Ersetzung case, fehlt noch der Doppelpunkt und man bemerkt hinterher, dass da schon ein case in XProfan war!

case mn$="JIN" : oc$ = "000"+"0"+"10"+"01"

Hätte man vorher zu einem
if( mn$ === "JIN" ) oc$ = "000"+"0"+"10"+"01";
machen sollen.

Mit etwas Geduld ist es aber geschafft!

Ein weiteres Problem ist das unterschiedliche Ereignismodell.

In XProfan habe ich mit einer verschachtelten Ereignisabfrage gearbeitet.
repeat' >>>>>>  Ereignisschleife  Halt/Weiter/Einzelschritt und MGA-Display >>>>>>>

    '-------                              (äussere Ereignisschleife)
    waitinput
    '-------
    ...

    repeat' innere Ereignisschleife

        '........
        waitinput' EREIGNISABFRAGE  für mögliche Aktionen:  X STOP Programm / weiter ausführen / einen Befehl weiter
        '........
        ...

Im Browser benutzt man Ereignis-Lauscher in der Form

mn.addEventListener( 'input', onMnInput );

für jedes Element und jedes Ereignis und ordnet dem eine Funktion zu.

Das wirft den ganzen Algorithmus in seiner Struktur über den Haufen. Man muss es gänzlich neu strukturieren.

Auf /dev  [...]  funktioniert jetzt erst einmal der Eintrag des 8 Bit Binärcodes in das Feld Op Code links neben Mnemonic.

Beim Test darauf achten, dass nur gültige Befehle zu einem sinnvollen Ergebnis führen, unsinnige Kombinationen ergeben immer den NOP Befehl 00000000.
 
22.12.2020  
 




HofK
Der Anfang für die Verbindung von 2D HTML/CSS GUI und 3D three.js RAM ist gemacht. Die binären Operationscodes werden in den RAM übertragen.

Allerdings ist die Sache noch nicht vollständig. Die Funktion restore_instruction( ); muss noch realisiert werden und die Adresse wird noch dezimal angezeigt. Auch gibt es Abweichungen wegen des Ereignismodells.



Aktuell bei /dev

-----
 
vor 31 Tagen  
 




p.specht
Tolles Lehrmittel! Bedeutet restore_instruction(), dass dein Programm sogar disassemblieren kann?
Frohe Festtage, Klaus!
 
XProfan 11
Computer: Gerät, daß es in Mikrosekunden erlaubt, 50.000 Fehler zu machen...
vor 31 Tagen  
 




HofK
Wenn man mit Hilfe der Buttons



im RAM vor und zurück geht, muss der Befehl (ebenso die Konstante) aus dem RAM wieder in der Programmieroberfläche rekonstruiert werden. Ansonsten wird der RAM Inhalt an der neuen Stelle mit den in der Oberfläche stehenden Werten überschrieben. Das ist gegenwärtig noch der Stand. Bald nicht mehr!

Der Code von XProfan muss angepasst übernommen werden.
'{--- Hilfsprozeduren Assembler ------

proc restore_instruction' Befehl (Eingabe)  mit Kommentar wiederherstellen

    settext mn% , left$( gettext$(RAM%, coderow%,3) , 3)' Mnemonic setzen
    settext op1%,  mid$( gettext$(RAM%, coderow%,3) , 5, 4)' Op 1 setzen
    settext op2%,  mid$( gettext$(RAM%, coderow%,3) ,10, 4)' Op 2 setzen
    settext opcomm%, trim$(mid$(comment$[coderow%],2,255))' Kommentar zum Befehlsetzen

endproc

proc restore_const' Konstante (Eingabe) mit Kommentar wiederherstellen

    settext coninp%, trim$( left$( gettext$(RAM%, conrow%,3) ,4) )
    settext concomm%, trim$(mid$(comment$[conrow%],2,255))

endproc

proc restore_from_RAM' Befehl oder Konstante aus RAM mit Kommentar wiederherstellen

    if (ramrow% > -1) AND (ramrow% < 128)' ramrow% ist -1 wenn auf "Teilzeile" am Ende der Gridbox geklickt wird!

        coderow% = ramrow%
        restore_instruction' Mnemonic Op1,2 und Kommentar in Eingabe-Edits setzen

    endif

    if (ramrow% > 127)  AND (ramrow% < 256)

        conrow%  = ramrow%
        restore_const' Konstante (Eingabe) mit Kommentar setzen

    endif

endproc


Wird etwas aufwändiger, da der RAM in 3D gestaltet ist.

-----------
 
vor 31 Tagen  
 




p.specht
Die Industrie ätzt Chips ja mittlerweile auch in 3D bzw. viel-lagig. Anders wären die Smarthandys ja nie so flach zu kriegen. Faszinierend!
 
XProfan 11
Computer: Gerät, daß es in Mikrosekunden erlaubt, 50.000 Fehler zu machen...
vor 31 Tagen  
 




HofK
Bisher bestand der RAM nur aus den 8 Bit Zellen in 3D. Da der Mensch die vielen Nullen und Einsen geistig aber in der Regel nicht verkraftet, habe ich die Assemblerbefehle danebengestellt.

Nach einigen Tests habe ich mich entschieden, diese als THREE.PlaneBufferGeometry zu realisieren. Dabei wird der dynamische Inhalt mittels Canvas Textur dargestellt.

Das ist nicht echt 3D, aber three.js 3D Text ist zu aufwändig und diese "Hilfsdarstellung" würde zu sehr vom eigentlichen RAM mit Nullen und Einsen in den transparenten 3D Zellen ablenken.

Da instanced Meshes zwar unterschiedliche Farben und Positionen der einzelnen Meshes unterstützen  [...]  , nicht aber unterschiedliche Texturen, muss man ein Array von Rechtecken erzeugen und positionieren. Das Seitenverhältnis der PlaneBufferGeometry entspricht dem von canvas.
const canvasW = 1664;// canvasH * 13
const canvasH = 128;
const txtGeo = new THREE.PlaneBufferGeometry( 9.1, 0.7 );// 13 : 1

for ( let i = 0; i < 256 ; i ++ ) {

    canvas.push( document.createElement('canvas') );
    canvas[ i ].width = canvasW;
    canvas[ i ].height = canvasH;
    ctx.push( canvas[ i ].getContext('2d' ) );
    canvasTexture.push( new THREE.Texture( canvas[ i ] ) );
    canvasMaterial.push( new THREE.MeshBasicMaterial( { map: canvasTexture[ i ], side: THREE.DoubleSide } ) );
    txtMesh.push( new THREE.Mesh( txtGeo, canvasMaterial[ i ] ) );
    txtMesh[ i ].position.x = 18;
    txtMesh[ i ].position.y = - i + 12;
    //txtMesh[ i ].position.z = 0.11;  //   TEST ////////////////////
    RAM.add( txtMesh[ i ] );
    txtAss = RAM$[ i ][ 3 ].padEnd( 16 ) + RAM$[ i ][ 4 ];
    changeCanvas( canvasTexture[i], ctx[i], txtAss );

}


In der animate Funktion aktualisiert man den Text.
txtAss = RAM$[ coderow ][ 3 ].padEnd( 16 ) +'NZVC'; // RAM$[ coderow ][ 4 ];	 //!!!!!!! TEST  'NZVC' !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
changeCanvas( canvasTexture[ coderow ], ctx[ coderow ], txtAss );

Dazu benutzt man die Funktion changeCanvas.



aktuell bei /dev 
 
vor 27 Tagen  
 




HofK
Beim RAM gab es noch einige Änderungen und er ist nun auch schon wesentlich funktioneller.

function changeCanvas( canvasTexture, ctx, txt )
ist nun
function canvasSet( texture, ctx, bgr, w, h, txt )

Dazu kommt
function selectrowcolor( row, color ) {

    txtAss = RAM$[ row ][ 3 ].padEnd( 16 ) + RAM$[ row ][ 4 ];
    canvasSet( cvAssTexture[ row ], ctxAss[ row ], color, cvAssW, cvAssH, txtAss );

}


um die aktuelle Assemblerzeile hervorzuheben. Bei XProfan erledigte das die Suche mit
selectstring(RAM%, -1, d255_to_bin8(coderow%))' aktuelle Befehlszeile im RAM markieren

in der Gridbox.

Hier sieht man, dass man Abläufe nicht so einfach übertragen kann.

Im Unterschied zur Windows Gridbox wird im Browser nur der Assemblerteil farblich hervorgehoben.

Man kann nun bereits im RAM (im Assemblerteil) herumklicken und dann links unter ASSEMBLER-COMMAND Befehle eingeben. Das sowohl mit der Auswahlliste, als auch durch Eintrag. Die Buttons für vorheriger/nächster Befehl funktionieren ebenfalls.

aktuell bei /dev 
 
vor 22 Tagen  
 




HofK
3D macht an einige Stellen erheblich mehr Code notwendig. Bei der XProfan Gridbox
var RAM%  = create("Gridbox", %hwnd, ramkopf$, 0, 4, 18, 379, 664)
bekommt man von Windows die Bedienung der Scrolleiste gratis dazu.

Für die Browservariante habe ich zwei 3D Pfeile gebastelt und sie mit Funktionalität versehen. Das wird mit raycast realisiert. Dabei funktioniert .name wie bei Radiobuttons als Gruppenname. Es wird also nur geprüft, ob das Element diesen Namen hat.




Mittlerweile kann man Assemblerbefehle und Konstanten eingeben und den grünen Startknopf drücken. Da werden bisher nur die Programmierelemente verborgen. Mit dem x Button neben STOP kommen sie wieder.

aktuell bei /dev  
 
vor 19 Tagen  
 




HofK
Seit Ende 2020 gibt es einen deutschen Kanal für three.js auf discord.



Da ist bisher noch nicht viel los. Gestern kam eine Frage zum Import von Modellen. Daraufhin habe ich mein altes Beispiel aktualisiert und gleichzeitig ES6 Module benutzt. Dabei 3 Varianten zur Einbindung der Module zum Test aufgelistet.
<script type="module">
// ----- import from the web -----
// current revision from the repository
/*
import * as THREE from 'https://threejs.org/build/three.module.js';
import { OrbitControls } from 'https://threejs.org/examples/jsm/controls/OrbitControls.js';
import { OBJLoader } from 'https://threejs.org/examples/jsm/loaders/OBJLoader.js';
import { MTLLoader } from 'https://threejs.org/examples/jsm/loaders/MTLLoader.js';
*/
// or a specific revision from a CDN ( Content Delivery Network, e.g.  https://www.jsdelivr.com/package/npm/three )
/*
import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.124.0/build/three.module.js';
import { OrbitControls } from 'https://cdn.jsdelivr.net/npm/three@0.124.0/examples/jsm/controls/OrbitControls.js';
import { OBJLoader } from 'https://cdn.jsdelivr.net/npm/three@0.124.0/examples/jsm/loaders/OBJLoader.js';
import { MTLLoader } from 'https://cdn.jsdelivr.net/npm/three@0.124.0/examples/jsm/loaders/MTLLoader.js';
*/
//  ----- import local -----
// NOTE! changed identifiers (.rev) and changed import statements at the beginning of the files
// https://hofk.de/main/discourse.threejs/Local%20use%20of%20the%20examples.pdf
// see https://hofk.de/main/discourse.threejs/Module%20usage.pdf
import * as THREE from'../jsm/three.module.124.js'; //
import { OrbitControls } from'../jsm/OrbitControls.124.js';
import { OBJLoader } from'../jsm/OBJLoader.124.js';
import { MTLLoader } from'../jsm/MTLLoader.124.js';

Siehe discord [...] 

und bei discourse [...] 
 
vor 15 Tagen  
 




HofK
Bei der CPU Simulation geht es stückweise weiter. Neben dem RAM ist nun auch in der CPU etwas darstellbar. Allerdings fehlt dort noch die Beschriftung der Bytes. Da sich die Übernahme des Codes der eigentlichen Verarbeitung recht schwierig gestaltet und fehleranfällig ist, habe ich einige JavaScript Erweiterungen eingebunden. Damit ist ein leichterer Vergleich des XProfan- und JS Codes möglich.
// JavaScript Syntax-Erweiterungen - z.T. Anpassungen an Original Quellcode (XProfan)
const gettext = ( elm ) => ( elm.innerHTML || elm.value );
const settext = ( elm, string ) => ( elm.innerHTML = string );
String.prototype.bin = function ( ) { return parseInt( this, 2 ) }// dezimaler Wert des Binärzahl-Strings
String.prototype.ord = function ( ) { return this.charCodeAt( 0 ) }// ANSI Code erstes Zeichens
String.prototype.val = function ( ) { return parseInt( this, 10 ) }// dezimaler Wert des Dezimalzahl-Strings
Number.prototype.chr = function ( ) { return String.fromCharCode( this ) }// Zeichen zum ANSI Code
Number.prototype.str = function ( ) { return this.toString( 10 ) }// Dezimalwert in String umwandeln

Die originalen JS Statements sind teilweise etwas umständlich/länger und nicht sehr übersichtlich. So ist .value kein Wert, sondern auch ein String. Mit
const gettext = ( elm ) => ( elm.innerHTML || elm.value ); und neuem .val wird es übersichtlicher und passt besser zu XProfan. Momentan ist noch nicht der gesamte Code derart umgestellt, 

Das .innerHTML stammt aus der Zeit, als HTML wirklich nur eine Seitenbeschreibung war und passt mit JS eigentlich nicht mehr. Aber solche "Alten Zöpfe" gibt es massenhaft bei der teils chaotischen Entwicklung in der IT.

Mit der JS-Anpassung an XProfan ist die Übernahme dann übersichtlicher.

Ein Beispiel aus define_constant:

Aus
settext conbin%, conbin$' binär anzeigen
settext conhex%, bin8_to_hex2(conbin$)' hexadezimal anzeigen
settext RAM%, conrow%, 2, conbin$' binär im RAM ablegen
sp_h$ = space$(5-len(coninp$)) +"h"' variable Leerzeichen vor h für hexadezimalen Wert
settext RAM%,conrow%,3,coninp$+sp_h$+gettext$(conhex%)' Wert im RAM darstellen
comment$[conrow%]  = ";"+concomm$' Konstanten-Kommentar in Kommentarfeld speichern

wird
settext( conbin, conbin$ );// binär anzeigen
settext( conhex, bin8_to_hex2( conbin$ ) );// hexadezimal anzeigen
RAM[ conrow ][ 2 ] = conbin$;// binär im RAM ablegen
sp_h$ = mkstr$(' ', 5 - coninp$.length )  + 'h'; // variable Leerzeichen vor h für hexadezimalen Wert
RAM[ conrow ][ 3 ] = coninp$ +sp_h$ + gettext( conhex );// Wert im RAM darstellen
comment$[ conrow ] = ";" + concomm$;// Konstanten-Kommentar in Kommentarfeld speichern

Da CPU und RAM in 3D dargestellt werden, musste ich intern für die Inhalte Variablen oder Datenfelder anlegen, aus denen dann die 3D Darstellungen dynamisch generiert werden. Das ist etwas mehr Aufwand als mit den Windows Controls in XProfan, aber andererseits erspart es Code.

Aus
whileloop 0,3

    settext R%[&loop],"00000000"'  D, A-Register mit 0 initialisieren
    settext S%[&loop],"00000000"' SD,SA-Register mit 0 initialisieren

endwhile

settext IR%, "00000000"' No Operation im IR

wird
for ( let i = 0; i < 4; i ++ ) {

    R[i] = "00000000";// D, A-Register mit 0 initialisieren
    S[i] = "00000000";// SD,SA-Register mit 0 initialisieren

}

IR = "00000000";// No Operation im IR

aktuell bei /dev  
 
vor 14 Tagen  
 



 
- Seite 40 -



HofK
Lange angekündigt ist es nun soweit.

Die anfängerfreundliche aber im professionellen Einsatz nicht so günstige Geometry verschwindet stückweise aus three.js. Dazu gibt es eine Diskussionsthema  [...] 

Das hat mich veranlasst, die alte Problematik der Performance noch einmal genauer unter die Lupe zu nehmen.
Siehe  [...] 

Dort auch der Link zur Lösung  [...] 

Bei BufferGeometrie muss man persönlich die zwei Dreiecke des Rechtecks in eine Materialgruppe packen. Bei der Umwandlung von Geometry zu BufferGeometry packt es das System irgendwie selbst. Und mehr Gruppen bedeutet mehr Last, also weniger Performance.
 
vor 8 Tagen  
 




HofK
Das Maschinenprogramm, der Binärcode läuft.

Wenn auch bisher nur mit einer minimalen Befehlsanzahl:

NOP
SWD
LDC

Nachdem ich zu NOP noch einige Befehle, teils ohne vollständigen Code, hinzugenommen hatte, gab es ein merkwürdiges Verhalten. Der Befehlszähler machte unerklärliche Sprünge.

Es hat eine Weile gedauert, bis ich die Ursache gefunden habe.

Die Zuordnung der Funktionen zur Befehlsausführung geschieht über eine stark verschachtelte Struktur mit switch, in XProfan select.

Im Unterschied zu XProfan muss in JavaScript jeder Fall mit break; abgeschlossen werden, da sonst der nächste Fall auch bearbeitet wird. Das ist für einige Anwendungsfälle eventuell sinnvoll, aber insgesamt eher nervig. Da die verschachtelte Struktur mit ca. 200 Zeilen und wenig Leerzeilen recht umfangreich ist, führen wenige fehlende break; zu merkwürdigem Verhalten.

Wenn ich seinerzeit die Simulation mit JavaScript programmiert hätte, dann hätte ich sicher eine andere Möglichkeit der Zuordnung genutzt. Denkbar ist ein mehrdimensionales Array. Da ich aber möglichst eng am Original-Quellcode bleiben möchte, habe ich keine andere Wahl, als alle breaks; korrekt zu setzen.

Ohne eine solche Faltung, sieht man überhaupt nicht mehr durch!



aktuell bei /dev 
 
vor 5 Tagen  
 




Antworten


Thementitel, max. 100 Zeichen.
 

Systemprofile:

Kein Systemprofil angelegt. [anlegen]

XProfan:

 Beitrag  Schrift  Smilies  ▼ 

Bitte anmelden um einen Beitrag zu verfassen.
 

Themenoptionen

123.655 Betrachtungen

Unbenanntvor 0 min.
Peter Max MüllerGestern (19:02)
Uwe LangGestern (12:31)
ByteAttackVorgestern (03:07)
Thomas Freier vor 4 Tagen
Mehr...

Themeninformationen



Admins  |  AGB  |  Anwendungen  |  Autoren  |  Chat  |  Datenschutz  |  Download  |  Eingangshalle  |  Hilfe  |  Händlerportal  |  Impressum  |  Mart  |  Schnittstellen  |  SDK  |  Services  |  Spiele  |  Suche  |  Support

Ein Projekt aller XProfaner, die es gibt!


Mein XProfan
Private Nachrichten
Eigenes Ablageforum
Themen-Merkliste
Eigene Beiträge
Eigene Themen
Zwischenablage
Abmelden
 Deutsch English Français Español Italia
Übersetzungen

Datenschutz


Wir verwenden Cookies nur als Session-Cookies wegen der technischen Notwendigkeit und bei uns gibt es keine Cookies von Drittanbietern.

Wenn du hier auf unsere Webseite klickst oder navigierst, stimmst du unserer Erfassung von Informationen in unseren Cookies auf XProfan.Net zu.

Weitere Informationen zu unseren Cookies und dazu, wie du die Kontrolle darüber behältst, findest du in unserer nachfolgenden Datenschutzerklärung.


einverstandenDatenschutzerklärung
Ich möchte keinen Cookie