[OpenGL-C++]Normalen im GL_TRIANGLE_STRIP / Membervar. mit dynamischem Speicherplatz

G

Green Mamba

Gast
Moin,

ich hab da mal 2 Prinzipfragen, wie werden bei OpenGL die Normalen bei einem GL_TRIANGLE_STRIP angegeben. Bei GL_TRIANGLES ja einfach immer eine Normale gefolg von den 3 Punkten, bei einem STRIP hingegen definiert nach dem 2. Punkt jeder neue Punkt bereits ein neues Dreieck.

Nun die andere Sache, wie macht man es am besten, wenn man eine Matrix oder Array als Membervariable hat, dieser aber dynamisch zur Laufzeit unterschiedlich viel Speicherplatz zuweisen will. Am besten mit Pointerarrithmetik, also auf keinen Fall einen Vektor, denn es geht um Performance, und da scheidet der Vector aus. Ich steh da momentan auf der eigenen Leitung irgendwie...

Vielen Dank schonmal für die Hilfe!

Schönen Gruß


Mamba
 
Zuletzt bearbeitet:
Green Mamba schrieb:
Nun die andere Sache, wie macht man es am besten, wenn man eine Matrix oder Array als Membervariable hat, dieser aber dynamisch zur Laufzeit unterschiedlich viel Speicherplatz zuweisen will. Am besten mit Pointerarrithmetik, also auf keinen Fall einen Vektor, denn es geht um Performance, und da scheidet der Vector aus. Ich steh da momentan auf der eigenen Leitung irgendwie...

Vielleicht steh ich gerade auf meiner Leitung, aber wäre die Lösung für das Problem nicht die althergebrachte Liste bzw. deren Abkömmlinge? Um damit noch mehr Rechenzeit zu sparen, kannst Du die Größe, die die Variable vermutlich erreichen wird, abschätzen und die Liste mit der entsprechenden Anzahl an Elementen initialisieren (Du weißt ja, Speicher anmieten kostet Zeit).

Oder habe ich Dich ganz falsch verstanden?

Gruß
Morgoth
 
Dynamisches Anlegen von Arrays/Matrizen:
Code:
// jetzt ist spätere Größe unbekannt
char** array;

// jetzt 5x4 Matrix anlegen
int x = 5;
int y = 4;
array = new char*[y];
for( int i=0; i<x; i++)
{
    array[i] = new char[x];
}

// später wieder löschen
for( int j=0; j<y; j++)
{
    delete array[j];
}
delete array;
Soltle gehen. Aber zur Sicherheit nochmal im Debugger überprüfen.
 
aah, ich hab in den letzten stunden intensiv rumgetestet, und bin schlussendlich vor einer halben stunde genau auf borons lösung gekommen. :D
die listen muss man mit einem iterator durchlaufen, ich wollte das aber mit pointer-arrithmetik machen, da schneller.
vielen dank euch beiden! :)
jetzt hab ich nur noch das problem mit den normalen. vielleicht weiß ja jemand wie sich das verhält.
 
Zuletzt bearbeitet:
Green Mamba schrieb:
auf keinen Fall einen Vektor, denn es geht um Performance, und da scheidet der Vector aus.

:rolleyes:

Den Vector zu übertreffen, muss man erstmal schaffen. Das ist garnicht so einfach (ist aber möglich). Der Vector arbeitet intern mit einem garantiert zusammenhängenden Stück Speicher. Von daher arbeitet er intern auch mit Pointerarithmetik. Wenn Du vor Benutzung des Vectors ein .resize (x) auf ihn machst, spart man sich man sich die Neuanforderung des Speichers. Damit ist er fast genauso schnell wie ein herkömmliches Array.
 
ich hab mal in einem anderen projekt testweise mit dem vector gearbeitet, und der unterschied war auf jeden fall messbar.
Damit ist er fast genauso schnell wie ein herkömmliches Array.
da sagst du es schon selbst, selbst ein array is lahmer als wenn du es direkt mit pointern machst. (mal abgesehen von compiler-optimierungen)
außerdem kann ich so komplett auf funktion-calls verzichten.
aber is auch eigentlich nicht so wichtig, denn ich habs ja nun so hinbekommen wie ich es haben wollte. :)
 
Solange Du mit Iteratoren arbeitest, werden die direkt in Pointer umgesetzt.

vector<int>::iterator it;

wird nach Ersetzen des Templates zu

int* it;

Okay, die STL garantiert das nicht, aber zo ziemlich jede Implementation macht es so. Die meisten Funktionsaufrufe eines Vectors sind auch trivial und daher inline.

Dass es trotzdem schneller geht, stelle ich nicht in frage. Der Mehraufwand bei der Programmierung und der vergleichsweise geringe Leistungsgewinn ist es aber recht selten wert.

Hmm... und ein array lahmer als wenn man's mit Pointern macht? Das kann ich jetzt aber nicht nachvollziehen.. Aber okay, ich glaub das wird schon bald OT :)
 
Zuletzt bearbeitet:
bei einem array wird beim zugriff auf das selbe die adresse des entsprechenden elements erst anhand der indices berechnet. wenn du mit einem pointer über ein array läufst, braucht nix berechnet zu werden.
beide lösungen werden in unterschiedlichen maschinencode umgesetzt. wenn ich mal zeit habe such ich die entsprechende passage aus meinem hardware-buch mal raus. "computer organisation & design"
es ist so dass eine pointer-anweisung nur etwa 2/3 - 1/2 der micro-ops dessen erzeugt was für eine array-anweisung erzeugt wird. die genaue begründung liegt in der hardware-architektur, sowie im pipelining des prozessors. ich kriegs auf jeden fall nicht mehr aus dem stehgreif hin. ;)
 
Beim Arrayzugriff wird auf die Startadresse der Offset addiert. Bei der Pointerinkrementierung wird die Größe des Datentyps auf den Pointer addiert. Macht im Assembler-Code keinen großen Unterschied. Die Anzahl der OpCodes ist aber auch nicht so wichtig. Inwiefern das Pipelining und Prefechting dabei eine Rolle spielt, kann manso nicht vorraussagen :) Und man muss die Daten richtig ausrichten, um mehr Cachehits zu bekommen. Dafür müsste man sich schon mit dem jeweiligen Prozessor auseinander setzen. Das überlass ich dann nachher doch lieber dem Compiler ;)
 
@Mamba
In meinem obigen Code sind zwei schwerwiegende Fehler.
Die beiden delete Anweisungen müssen ein [] enthalten, da ja in beiden Fällen ein Array dynamisch angelegt wurde.
Sonst hast du ein Speicherleck, und das wollen wir ja nicht.

Also
Code:
for( int j=0; j<y; j++)
{
    delete [] array[j];
}
delete [] array;
So ist es richtig.
 
Zuletzt bearbeitet:
danke dir boron, allerdings hatte ich das in meiner lösung schon intuitiv so gemacht. :)
habe auch das problem mit den normalen gelöst. man gibt einfach nach jedem punkt eine normale an, bin mir zwar nicht 100%ig sicher, aber die beleuchtung sieht auf jedenfall gut aus so! :daumen:
 
Hmm zu der Geschwindigkeitssache mit dem Vektor hatte ich vor kurzem doch nochmal ein paar Erkenntnisse :)

Ein Vektor ist in der Tat viel langsamer, wenn man ständig neue Objekte davon anlegt. Oder auch, wenn man eine riesige Anzahl von Vektoren hat. Denn ein Vektor braucht zur internen Verwaltung drei Zeiger. Bei einer relativ geringen Datenmenge, die man im Vektor speichert, ist das dann ein ziemlich großer Overhead.

Hat man aber nur einen Vektor und beschafft sich mit .rezize () gleich die entsprechende Menge an Speicher, so sind die Zugriffe quasi genauso schnell wie mit einem Array.
 
Naja, keine Ahnung, ich hab beim Programmieren lieber die ganze Kontrolle, und verlass mich nicht auf sowas. ;)
Habe das ganze mitlerweile noch anders gelöst, denn in meinem ersten Ansatz wurde meine Geometrie für jeden Frame über den AGP-Bus gefeuert, jetzt liegt alles schön im Grafikram. :D
Manchmal sieht man den Wald vor lauter Bäumen nicht mehr. ^^
Besser gehts nicht mehr, und Gedanken um die Speicherverwaltung brauch man sich dann auch nicht mehr zu machen. :)
(Natürlich nur in dem einen Fall)
 
Zuletzt bearbeitet:
Boron schrieb:
@Mamba
In meinem obigen Code sind zwei schwerwiegende Fehler.
Die beiden delete Anweisungen müssen ein [] enthalten, da ja in beiden Fällen ein Array dynamisch angelegt wurde.
Sonst hast du ein Speicherleck, und das wollen wir ja nicht.

Also
Code:
for( int j=0; j<y; j++)
{
    delete [] array[j];
}
delete [] array;
So ist es richtig.


reicht es nicht mit "delete[] array;" den pointer des gesamten arrays zu löschen?
und müsste es nicht wenn, dann
Code:
for( int j=0; j<y; j++)
{
    delete array[j];
}

sein?

afaik benutzt man "delete[]" doch für pointer eines gesamten arrays oder nicht?

also ich benutze bei char*-s auch nur 1x delete[] - und der char* ist ja nichts weiter als ein pointer auf einen array.
 
Die Regel dafür ist ganz einfach. Wenn der Speicher für etwas bei new mit [] angefordert wurde, so muss dieses auch bei delete wieder stehen. Vermischt man beides, so gibt das undefiniertes Programmverhalten.


Code:
array = new char*[y]; // [] verwendet
for( int i=0; i<x; i++)
{
    array[i] = new char[x]; // hier auch

Achso, das char* würde ich bei dem new klammern. Also new (char*)[y] Ich bin mir nicht wirklich sicher, wie das interpretiert wird. Es gibt da sehr perverse Schreibweisen :)
 
Zuletzt bearbeitet:
Das x muss ein y sein...
Boron schrieb:
Code:
// jetzt ist spätere Größe unbekannt
char** array;

// jetzt 5x4 Matrix anlegen
int x = 5;
int y = 4;
array = new char*[y];
for( int i=0; i<[COLOR=Red][B]x[/B][/COLOR]; i++)
{
    array[i] = new char[x];
}

// später wieder löschen
for( int j=0; j<y; j++)
{
    delete array[j];
}
delete array;
Code:
// jetzt ist spätere Größe unbekannt
char** array;

// jetzt 5x4 Matrix anlegen
int x = 5;
int y = 4;
array = new char*[y];
char **temp = new char[x*y];
for( int i=0; i<y; i++) array[i] = &temp[i*x];

// später wieder löschen
delete [] array[0];
delete [] array;
 
Zuletzt bearbeitet:
Zurück
Oben