OpenGL ES, Verständnis Tutorial 3D Würfel

Hallo
Ich fand im Internet dieses Tutorial.Doch finde ich, dass es dort schlecht beschrieben ist. Ich bitte darum, mir Auskünfte über folgende Ausschnitte zu geben oder vielleicht weiß jemand ein besseres Tutorial zu diesem Thema.

1.MyGLRenderer.java
1.1 Der ganze Inhalt von onSurfaceCreated(GL10 gl, EGLConfig config) , vor allem diese Variablen und die Werte darin:

float lightAmbient[] = new float[] { 0.2f, 0.2f, 0.2f, 1 };
float lightDiffuse[] = new float[] { 1, 1, 1, 1 };
float[] lightPos = new float[] { 1, 1, 1, 1 };

1.2 Wozu ist in onDrawFrame(GL10 gl) das ganze Zeug um “cube.draw(gl);”
drumm herum ? Diese Methode müsste doch die einzige von Belang sein oder?

2.MyCube.java
2.1 Im Konstruktor sind doch in den beiden Arrays eigentlich die Koordinaten angegeben doch was hat insbesondere der doch recht willkürlich scheinende Wert von “one” zu bedeuten ? Und warum sind die Koordinaten nur Plus und Minus Werte EINER Zahl ?

2.1 Eigentlich kommt es beim Zeicnen doch nur auf die Koordinaten an, was hat aber der Restcode in draw(GL10 gl) zu bedeuten ?

                gl.glColor4f(1, 1, 1, 1);
		gl.glNormal3f(0, 0, 1);
		gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
		gl.glNormal3f(0, 0, -1);
		gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);

		gl.glColor4f(1, 1, 1, 1);
		gl.glNormal3f(-1, 0, 0);
		gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);
		gl.glNormal3f(1, 0, 0);
		gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);

		gl.glColor4f(1, 1, 1, 1);
		gl.glNormal3f(0, 1, 0);
		gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);
		gl.glNormal3f(0, -1, 0);
		gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);

Auch wäre einer Erklärung der Methoden und derer Parameter hilfreich, oder eine Dokumentation mit diesen Infos(Hab selbst nichts gescheites erfunden)

Danke

Moin,

http://nehe.gamedev.net/

ich habe da aber nur kurz rein geschaut. Vom Thema habe ich quasi null Ahnung.

hand, mogel

da steht doch kurz davor der Kommentar // Define the lighting, später auch // What is the cube made of? usw.,

ist doch halbwegs verständlich, es sei denn du kennst noch rein gar nichts dazu, und selbst dann steht es ja quasi da, dass es eine Lichtquelle braucht um was zu sehen usw.,
all solche Dinge müssen auf irgendeine Weise formuliert werden, die Position, die Lichtstärke usw.,

ich bin (auch) kein Experte für nähere Details, aber selbst wenn lohnt es sich kaum dass alles hier aufzuschreiben,
ein gutes Tutorial brauchst du, das ist klar, von mir leider kein Link

ziemlich dasselbe, Kommentare a la
// Clear the screen to black
// Position model so we can see it
// Set rotation angle based on the time
sagen doch alles,
anscheinend dreht sich das Ergebnis, insbesondere das muss dir doch sagen dass simples Zeichnen nicht reicht,
sondern auch ein bisschen zu errechnen ist wie es aktuell aussehen soll, rotieren lassen,

hinder dem draw-Befehl auch überdeutlich noch Code nur zur FPS-Berechnung

ganz willkürlich ist 65536 nicht, das ist 2^16, die Anzahl verschiedener Werte in 2 Bytes oder ein char,
genaue Bedeutung kenne ich hier nicht


zum Würfel siehe auch dieses Bild

eine Art Einheitswürfel mit Koordinaten,
in dem Code verschoben so dass der Ursprungspunkt des Raumes mit Koordinaten 0,0,0 keine Ecke bildet sondern genau in der Mitte des Würfels liegt,

jede Seite ist anscheinend durch 4 Punkte, 4x 3 Koordinaten beschrieben
bei

				-half, -half, half, half, -half, half,
				-half, half, half, half, half, half,

ist der 3. Wert jeweils gleich, sei das die Koordinate B im Bild, die geht ja auch nach vorne,
die Punkte Blau (0,0 ohne die dritte Koordinate), Magenta (1,0), Weiß (1,1) und Cyan (0,1) bilden die Frontseite des Würfels im Bild,
verschiebt man die zugehörigen Koordinaten, dann kommt eben (-half, -half), (half, -half), (half, half) und (-half, half) raus, nicht ganz in Reihenfolge

bei texCoords sind es je Seite nur 8 Werte, unterschiedliche Kombinationen wiederum von
(0, one), (one, one), (0, 0), (one, 0), was wieder einmal die allgemeinen 4 Eckpunkte beschreibt

vielleicht ist da schon 2D gegeben und es muss nur die ganze Fläche abgesteckt werden,
mit one statt half falls von einer der Ecken begonnen wird…,
na, recht viel Spekulation dabei

zu 2.1. fällt mir kein Blah blah ein, irgendwas ist wohl zu zeichnen,
teste doch auch jeweils wie es aussieht wenn du was weglässt

edit:
Links gibts doch nun viele, etwa

sind natürlich nicht kinderleicht…

EDIT: Zu langsam :frowning:

Hmja, da könnte man laaaange drüber schreiben. (Und wenn man mal nach sowas wie „OpenGL“ websucht, findet man raus: Das hat auch schon der eine oder andere getan :D)

Deswegen nur kurz:

Die konkreten Zahlen dort sind die Lichtfarbe- und Position:
Ambient=Die Farbe des Lichts, das „überall“ ist (damit Bereiche im Schatten nicht komplett schwarz sind)
Diffuse=Die Farbe des eigentlichen Punktlichts
Position: Die Position des Lichtes im 3D-Raum

Danach kommt das gleiche noch für Materialfarben. Insgesamt kann man das, was in der Methode gemacht wird (wenn man will) erstmal als „Boilerplate-Code“ ansehen: Das muss man halt so (oder so ähnlich) machen, damt was dargestellt werden kann.

Damit wird erstmal der Bildschirm gelöscht, und danach noch gesagt, WO der Würfel hingezeichnet werden soll.

Der Wert ist nicht willkürlich, sondern 2^16-1. Die Koordinaten sind dort als integer angegeben. Warum er das so gemacht hat, erschließt sich mir auch nicht direkt (und ehrlich gesagt auch nicht, warum das so funktioniert…). Eigentlich sollte man da floats mit 1.0f und 0.5f verwenden…

Er zeichnet auf … etwas komplizierte… weise jede einzelne Seite des Würfels, mit eigener Normale und eigenen Texturkoordinaten. Das muss man nicht „genau so“ machen. Insbesondere würde man das bei einem komplexeren Objekt nicht mehr so machen, sondern alle relevanten Informationen in einem VBO bereitstellen.

Apropos VBO: Die meisten OpenGL-Tutorials sind so gesehen veraltet. Sowas wie das Matrix-Zeug mit „glTranslatef“ usw. gibt es in neueren OpenGL-Versionen offiziell nicht mehr. Da wird alles in Shadern gemacht. Das ist dann NOCH tausend mal komplizierter, und mit NOCH mehr Boilerplate-Code den man nicht versteht.

Aber es gibt Abhilfe:
Compilierbare samples: https://github.com/mschorn/net.mschorn.sandbox/tree/master/src/main/java/net/mschorn/sandbox/lwjgl
Modernes GL Tutorial: http://www.arcsynthesis.org/gltut/

Befehlsreferenz: https://www.opengl.org/sdk/docs/man/docbook4/xhtml/glDrawArrays.xml
(Sowas wie glDrawArrays – DGL Wiki ist für Delphi, aber das ist meistens egal, da sind einige Seiten ganz gut aufbereitet)

Warum ? Koordinaten sind doch eigentlich im Hunderter bereich, Mein Bildschirm ist beispielweise 800x400, da kommt man mit 0,5 doch nicht besonderes weit ?

Und was bedeutet diese Zahl ?

eine 1.0 wäre auch nur eine relative Angabe, z.B. X doppelt so lang wie Y,
auf Bildschirmgröße umrechnen müsste man das jeweils noch


‚65536 opengl‘ in Suchmaschine führt übrigens u. a. zu

mit

[…] The thing is, the HA tutorial has you build a spinning cube and uses very large int values. The cube is basically 65536x65536.
[…] NeHe tutorial feeds the vertex/texture buffers in as GL_FLOAT while the HA feeds them as GL_FIXED. Changing the latter to the former results in a lot of ugly planing.
[… Answer:] I’m not sure what this HA tutorial is, but check if they’re using the fixed-point versions (generally with a x suffix instead of f) of the various OpenGL ES functions. If so, remember that the OpenGL ES fixed-point format is S15.16, so 65536 maps to 1.0f or thereabouts.


hier ein 7seitiger Thread (ohne Java)
http://forum.nevercorner.net/viewtopic.php?id=2302
mit im ersten Posting

[…] This is significant because there’s a constraint common to most implementations of our target API, GL ES 1.1: the use of 16-bit unsigned integers in element array buffers. This imposes a limit of 65536 unique vertices in each individual draw call. […]

65535 findet anderes ähnliches

irgendein Umrechenfaktor und anscheinend nur ein Wissenspunkt von einem 700 Seiten-Buch, welches man wohl dazu lesen sollte,
falls es es bestenfalls gibt, ansonsten wohl so wie hier gelandet, richtig…


mit 5 Fragen wirst du nicht weit kommen, entweder weniger kritisch nur Beispiele übernehmen,
maximal noch bisschen Variation ausprobieten, smart aus Suchmaschinen Ergänzungen (z.B. auch einzelne Befehle)

oder Tage/ Wochen/ Monate an Zeit investieren, wobei es da auch keinen Automatismus zum Erfolg gibt,
deine Fragen lassen mich etwas zweifeln zu so einem komplizierten Thema, vorsichtig ausgedrückt :wink:
z.B. sollte sich all das selber finden lassen, Sekunden in Suchmaschinen

Ahja, nach sowas wie dem GL_FIXED hatte ich kurz im Code gesucht, es dann aber übersehen (weil ich auch das Stichwort wonach ich suchen mußte, nicht kannte - ich wußte nur: Irgendwas anderes als GL_FLOAT :rolleyes:

Die Koordinaten, die dort angegeben werden, sind “Weltkoordinaten”. Die haben mit den Koordinaten, die irgendein Objekt auf dem Bildschirm hat, nichts zu tun. (“Nichts” ist zu strikt - siehe http://forum.byte-welt.net/threads/12062-2d-Szene-Bildschirm-zu-Weltkoordinaten und verwandte Threads ;)). Auf jeden Fall kannst du einen Würfel der Größe 1x1x1 bildschirmfüllend darstellen, oder auch einen Würfel der Größe 1000x1000x1000. Üblicherweise verwendet man (wenn es keinen Grund gibt, etwas anderes zu machen) in solchen Fällen den “Einheitswürfel”, oder einen Würfel bei dem alle Eckkoordinaten +/-1 sind (da gibt’s Gründe dafür, das würde jetzt zu weit führen…)

2^16-1 ist einfach der größte Wert, der mit einer (vorzeichenlosen) 16bit-Zahl dargestellt werden kann.

In diesem Zusammenhang WICHTIG: Bei dem, was ich bisher gesagt hatte, fiel die Tatsache, dass das auf Android laufen soll, unter den Tisch. Aber auf Android läuft (“üblicherweise”) erstmal nur OpenGL ES*. Das ist eine etwas andere Welt. Mit den Details kenne ich mich nicht aus, aber ich weiß, dass es dort bestimmte Funktionen NICHT gibt, und dass es u.U. bestimmte Dinge NICHT kann - z.B. Koordinaten in bestimmten Formaten verarbeiten (was ein Grund für den Autor gewesen sein könnte, nicht GL_FLOAT und 1.0, sondern GL_FIXED und 65535 zu verwenden.

  • edit SlaterB: Titel weiter angepasst

Zum Verlikten Thread(Ich will meinen Testwürfel am Bildschirm plazieren):
Was ist eine Matrix ?
Wie kann ich den Würfel dann mit Bildschirmkoordinaten plazieren ?

Kommando Zurück !
Ich hab noch ein Anderes Tutorial durchgearbeitet!
Doch da wird GL ES 2 verwendet und es kommt immer wenn ich starte der Fehler:
called unimplemented OpenGL ES API

such es dir aus :slight_smile:
[ul]
[li]http://de.wikipedia.org/wiki/Matrix_(Film)[/li][li]http://de.wikipedia.org/wiki/Matrix_(Mathematik)[/li][/ul]

Ohne dass das jetzt zu sehr nach „Bashing“ klingen sollte: Die Sätze „Ich will ein OpenGL-Programm schreiben“ und „Was ist eine Matrix?“ passen irgendwie nicht zusammen.

Die „Grundlagen“ dafür hatte ich damals (wir hatten ja nix :frowning: ) in Chapter 3 - OpenGL Programming Guide gelernt. Das ist heute leider veraltet, aber die Mathematik war immer gleich, ist noch gleich, und wird immer gleich bleiben. (Wie man das heutzutage macht, steht u.a. um http://arcsynthesis.org/gltut/Positioning/Tutorial%2006.html herum, es ist aber etwas schwieriger, da mit dem Finger auf „die Stelle“ zu zeigen, wo es erklärt wird…)

Ok, ich habs verstanden(Glaub ich) ich mach gerade dieses Tutorial(Scrollen bis: 2.8-6. Das sind Würfel mit Texturen, ich hab alles genauestens befolgt(Später sogar Copy & Paste) und trotzdem wird nicht mein Bild sondern nur Weiß angezeigt auf dem Würfel.

der Würfel an sich funktioniert?

klingt ja ‘nur’ nach der Textur, und wie man sich an solchen Stellen immer denken kann (etwa auch Anzeigen eines Bildes in simplen Swing)
ist ein Dreh- und Angelpunkt das Laden des Bildes von der Festplatte (oder welch neumodisches Device auch immer…)

ehe.png"
InputStream istream = context.getResources().openRawResource(R.drawable.nehe);```
steht dort, hast du beachtet, nachvollzogen, schon irgendwo erfolgreich durchgeführt, 
wie du das PNG-Bild irgendwo ablegen und noch woanders konfigurieren musst?

etwas später steht auch minimal etwas zum Bild im Text, 
das TODO dabei ist verdächtig, aber vielleicht auch nur das zu OpenGL und dann reicht alternativ der fertige Code


> We store the texture image "nehe.png" into folder "res\drawable".

> The following steps are needed to setup texture and load an image:
>     1. [TODO]


und im Link zum Anfangsposting war auch eine Textur, Blume, ging diese?

-------

teste, aus dem Stream 100 Bytes zu lesen, logge sie irgendwo, kommt etwas an oder Stream leer?

Der würfel funktioniert, ist aber weiss.
Das bild ist in res/drawable und ist auch über R.drawable ereichbar, es ist eine .bmp datei und 100 mal 100 pixel.Der Würfel mit der blume ging gar nicht, nichtmal der Würfel, da trat irgendwo beim Texturladen eine NullPointerException auf.
wenn ich das “Log.d(“is”, istream);” schreibe, wird bei LogCat nichts ausgegeben

‘Hello World’ ist das einfache erste Programm, die Ausgabe darin gleichzeitig der wichtigste Befehl, den es gibt,
bevor keine Ausgabe kommt kann man nichts wirklich über ein Programm wissen

wenn etwas mittelkompliziertes an Ausgabe nicht geht, dann muss man einen Schritt zurückgehen,
geht eine Ausgabe ‘Test’ zu Beginn der Methode loadTexture?

aber auch möglich, dass die Methode nie aufgerufen wird,
dann irgendwo anders, an 20 Stellen im Programm, etwas ausgeben,

wenn nie irgendwo etwas erscheint, dann über die Ausgabe selber nachdenken,
bevor die nicht funktioniert kann man nichts anderes anfangen, muss man erstmal ein Hello World bauen,

helfen kann ich dabei kaum, aber das ist zumindest ein weitaus einfacheres Ziel (und dabei noch wichtiger!) als 3D-Grafiken

usw., aber das sind zig simple Grundlagen die zur Programmierung dazugehören, können kaum alle hier besprochen werden

System.out.println(); kenne ich, dachte aber, dass er in android nicht funktioniert.

ja - aber Android hat dafür andere Methoden um etwas zu Loggen

Wenn ich das “System.out.println(“geht”);” oder das “Log.d(“ff”, “geht”);” am Anfang der loadTexture methode schreibe wird bei LogCat trotzdem nichts ausgegeben.

was bedeutet das ‚trotzdem‘ in deinem Satz?
ich kann mich nur wiederholen, ohne Log-Ausgaben bist du blind auf Glatteis im Programm,

  • vielleicht wird die Methode eben nie ausgeführt wegen Exception, von der du ohne Logging nichts mitbekommst,
  • vielleicht funktioniert das Programm aber doch bestens, kommt zumindest dort vorbeit, nur ist Log.d(„ff“, „geht“); ein nicht-geeigneter Befehl (ich habe keine Ahnung)
  • oder vieles andere

ich rate dir (nur wiederholend das gleiche) dazu, Programme zu benutzen, deren Vorgehen man nachvollziehen kann,
dazu ist das erste Mittel Log-Ausgaben

es kann in jeder Umgebung, in jeder normalen Programmiersprache kaum ein anderes Programm am Anfang geben als das welches „Hello World“ ausgibt :wink:
und diesen Stand darf man nie vergessen, egal ob später 3D-Grafiken oder Atomprogramm auf dem Mars zu steuern,

immer müssen Log-Ausgaben funktionieren,
wenn mal nicht mehr (oder vorher gar nicht dran gedacht), dann ist alles andere zu vergessen und erst das (wieder) herzustellen:
schreibe ein Programm, welches Hello World loggt, egal wie, ich kann nicht direkt helfen (könnte vielleicht suchen, aber naja…),
sollte doch wohl machbar sein

sofern als erster Schritt Logging besteht, logge als zweiten Schritt manches, um eine Vorstellung zu bekommen, was ausgeführt wird,
wenn du siehst dass etwas ohne Textur gezeichnet wird, dann sollten auch Logging dort beim Zeichnen funktionieren

sofern vieles andere schon funktioniert kümmere dich um loadTexture(),
wie jede Methode (zumindest im Fehlerfall :wink: ) sollte diese am Anfang nichts anderes als

// Logging 'Methode loadTexture', evtl. return null;
}

lauten, wenn das funktioniert kann man weiterarbeiten,
wenn es nicht kommt dann schauen wo es aufgerufen wird und dort weiter untersuchen, ob Code ausgeführt oder abgebrochen wird,

dabei dann dort auch wieder mit Log bei Methodenstart beginnen usw. bis irgendwann tatsächlich bei Code, der auch ausgeführt wird,
dann auf Kontrollstrukturen wie if und Schleifen zu achten,
auch ein try/catch für Exceptions mit Logging im catch bietet sich an

Laut Internet geht “Loggen” mit Log.d(), Log.i(), …
Aber selbst wenn ich Log.i(“test”, “hier”) an den Anfang von onCreate der Activity schreibe wird nichts ausgegeben.
Außerdem hab ich herausgefunden, dass es nicht funktioniert, weil ich das Bild in das GL10 von onSurfaceCreated lade und nicht in das GL10 von onDrawFrame. wenn ich es die Lademethode aber in DrawFrame ausführe ruckelt es sehr(Würfel dreht sich stückweise oder gar nicht)