Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

CeDoMain

Alter Hase

  • »CeDoMain« ist der Autor dieses Themas

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

1

06.05.2014, 20:18

std::vector in std::vector einfügen - geht das ohne schleife?

Hallo Leute,

ich habe ein Geschwindigkeitsproblem:

Ich habe einen Vector mit DWORDs gefüllt. Nun will ich einen zweiten Vector (auch mit DWORDs) an den ersten anhängen! Ich habe das mit einer for-Schleife gelöst, die durch den zweiten Vector durchiteriert und für jedes Element "push_back()" aufruft. Das ist aber zu langsam ... weil das mit vielen Vectoren passieren muss (es werden nicht nur einer angehangen, sondern über 1000). Kann ich das anders lösen? So wie es in C# .Net mit AddRange() geht, wer das zum Beispiel kennt. Oder kann ich schneller durch den Vector iterieren als mit einer for-Schleife? Oder ganz anders: Gibt es andere c++ Arrays (keine externen Libs!) mit denen das besser geht bzw. die speziell dafür sind?

Wäre cool, wenn es eine schnellere Lösung gäbe! :D
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

2

06.05.2014, 20:21

Schau dir mal std::vector::insert() an. Die Frage, die du dir an diesem Punkt aber unbedingt stellen solltest, ist, wieso du überhaupt meinst, tausende std::vector aneinanderhängen zu müssen!?

CeDoMain

Alter Hase

  • »CeDoMain« ist der Autor dieses Themas

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

3

06.05.2014, 20:31

OK vielen Dank! Dann muss ich das so machen:

C-/C++-Quelltext

1
2
3
4
vectorAll.Insert(vectorAll.end(), vector1.begin(), vector1.end());
vectorAll.Insert(vectorAll.end(), vector2.begin(), vector2.end());
vectorAll.Insert(vectorAll.end(), vector3.begin(), vector3.end());
vectorAll.Insert(vectorAll.end(), vector4.begin(), vector4.end());
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

CeDoMain

Alter Hase

  • »CeDoMain« ist der Autor dieses Themas

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

4

06.05.2014, 20:36

Schau dir mal std::vector::insert() an. Die Frage, die du dir an diesem Punkt aber unbedingt stellen solltest, ist, wieso du überhaupt meinst, tausende std::vector aneinanderhängen zu müssen!?

Ich schreibe ein Spiel! Es hat eine OpenWorldMap, die aus Blöcken besteht (wer jetzt ein Dejavu hat - erfasst!). Jeder dieser Blöcke wird durchgegangen und für Blöcke die an einen Luft Block grenzen, werden aus einem Vector die Vertices für diesen Blocktyp in einen Vector eingelesen, der nachher gerendert wird! Für jeden Blocktyp stehen sechs Vectoren bereit, in denen die Vertexdaten für jede Blockseite stehen. Verstehst du?
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

5

06.05.2014, 20:54

Ich hoffe, du machst das einlesen nicht in jedem Frame :D

Ansonsten: Ist denn die Geometry eines jeden Blocks nicht gleich? Wozu brauchst du dann Kopien von den ganzen Vertices? Reicht es nicht aus, wenn du einfaches Geometry Instancing nutzt?
EnvisionGame(); EnableGame(); AchieveGame(); - Visionen kann man viele haben. Sie umzusetzen und auf das Ergebnis stolz zu sein ist die eigentliche Kunst.

CeDoMain

Alter Hase

  • »CeDoMain« ist der Autor dieses Themas

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

6

06.05.2014, 21:06

Ich hoffe, du machst das einlesen nicht in jedem Frame :D

Nene so schlau bin ich schon! ;) Ich mache das in nem Thread und auch nur, wenn der Chunk (die Blöcke sind Chunkweise gespeichert) geupdatet werden muss (weil sich ein Block ändert || ganz zu Anfang).

Geometry eines jeden Blocks nicht gleich

Nein leider nicht! Viele Blöcke sind natürlich Kuben, aber eben nicht alle! z.B. Glascheiben oder Zäune. (Wem jetzt nich aufgeht worum es sich hier handelt... ^^ )

Eine Frage hätte ich noch! Wenn ich durch den Vector iteriere und dabei die Position eines Vertex ändern will. Mach ich dass dann so:

C-/C++-Quelltext

1
2
for(Iterator i = Vector1.begin(); i != Vector1.end(); i++)
VectorAll.push_back(i.Position + Vector(5, 2, 4));


Also alle Vectoren sollen hier um 5|2|4 verschoben werden! Geht das mit dem "+" in den Klammern? Und ist die for-Schleife richtig? Geht das schneller mit ner "int i"-Schleife oder mit ner "iterator i"-Schleife?

PS: Ich gehe davon aus, dass ein passender Vector(x, y, z)-Konstruktor vorhanden ist und die Eigenschaft "Position" heißt!
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

7

06.05.2014, 21:22

Die Schleife an sich ist so richtig, man sieht sehr selten, dass dazu ein int-Wert als Iterator verwendet wird ;)

Das + funktioniert nur, wenn der + operator entsprechend überschrieben wird.

Zitat

Nein leider nicht!


Dann würde ich an deiner Stelle trotzdem nicht die einzelnen Daten für jeden einzelnen Block kopieren, sondern auch hier lässt sich Geometry Instancing anwenden ;)

C-/C++-Quelltext

1
2
3
4
// pseudocode
enum EBlocktype { eBlockTypA, eBlockTypB, eBlockTypC }
blocks[10][10].type = eBlockTypA;
blocks[10][10].position = Vector3(10, 70, 10);
EnvisionGame(); EnableGame(); AchieveGame(); - Visionen kann man viele haben. Sie umzusetzen und auf das Ergebnis stolz zu sein ist die eigentliche Kunst.

birdfreeyahoo

Alter Hase

Beiträge: 756

Wohnort: Schorndorf

Beruf: Junior Software Engineer

  • Private Nachricht senden

8

06.05.2014, 21:50

Kannst du nicht Klassen für die Blöcke schreiben, die eine Methode implementieren, welche ihre Vertices relativ zu ihrer eigenen Position zurückgibt? (statisch dann, weil jede Instanz gleich)?

CeDoMain

Alter Hase

  • »CeDoMain« ist der Autor dieses Themas

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

9

07.05.2014, 21:08

Das + funktioniert nur, wenn der + operator entsprechend überschrieben wird.
Das würde dann heißen, dass der Operator einen Positionsvektor zurückgibt! Wie mache ich das, dass aber dann ein Vertex eingefügt wird? Also die Position geändert, aber der Normalen- und Texturvektor bleibt bestehen. Muss ich dann einen "+=" Operator nehmen? Und wie muss der überladen werden oder mache ich das mit casten? Geht das überhaupt ohne eine "Temporäre" Variable erstellen zu müssen?

Dann würde ich an deiner Stelle trotzdem nicht die einzelnen Daten für jeden einzelnen Block kopieren, sondern auch hier lässt sich Geometry Instancing anwenden ;)
Und wie mache ich das beim Rendern dann? Ich kann doch nicht für mehrere Millionen Blöcke einzeln die Blöcke rendern? Das braucht doch viel länger, als einen (oder ein paar) VertexBuffer zu rendern...

Kannst du nicht Klassen für die Blöcke schreiben, die eine Methode implementieren, welche ihre Vertices relativ zu ihrer eigenen Position zurückgibt? (statisch dann, weil jede Instanz gleich)?
Auf die Idee bin ich schon gekommen ;) Ich habe mir einen ResourceLoader geschrieben, der die Texturen und Modelle für jeden Blocktyp aus (mehreren) Textdateien liest! Von dem Loader kommen dann auch die Blockmodelle in Form von Vertexvector-Arrays.

Und ich habe noch eine Frage zu Arrays: Ich speicher die Map Chunkweise (in 16 x 16 "Türmchen") in einem Array ala

C-/C++-Quelltext

1
2
BlockWorld_Chunk* Chunks;
Chunks = new BlockWorld_Chunk[32*32];
Auf das Array wird mit einer Methode zugegriffen, die jedem X|Z Koordinatenpaar einen Index im Array zuweist (Index = X + Z * 32). Wenn ich nun jeden Chunk im Array um eine Position in X-Richtung verschieben will, dann wäre das ja ein heftiger Aufwand, denn die Chunks müssten zwischengespeichert werden und dann komplett verschoben werden. Das wären ja riesige Datenmengen - also sehr langsam! Kann ich das anders machen, indem ich nur die Addressen im Array speichere und diese dann verschiebe? Oder gibt es da noch andere Arraytypen oder Methoden?
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

10

07.05.2014, 22:22

Zitat

Wie mache ich das, dass aber dann ein Vertex eingefügt wird?

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct Vertex
{
    float x, y, z;

    Vertex(float x, float y, float z) ...
};

struct Vector3
{
    float x, y, z;

    Vertex operator+(const Vector3& v)
    {       
        return Vertex(x + v.x, y + v.y, z + v.z);
    }
};


Zitat

Und wie mache ich das beim Rendern dann? Ich kann doch nicht für mehrere Millionen Blöcke einzeln die Blöcke rendern?

Es wird ein Buffer erzeugt, der für jeden Block beliebige Informationen speichert (z.B. Position und rotation). Dieser wird in einem Call mit den Vertices und den Indizes (jeweils für EINEN Blocktyp) zur GPU geschickt und schonst kannst du mit deinem Shader eine ganze Reihe an Objekten zeichnen. Mit nur einem API Call ;)

Direct3D9: http://msdn.microsoft.com/en-us/library/…9(v=vs.85).aspx
Direct3D10: http://www.rastertek.com/dx10tut37.html
Direct3D11: http://www.braynzarsoft.net/index.php?p=D3D11Instancing

Zitat

Wenn ich nun jeden Chunk im Array um eine Position in X-Richtung verschieben will

Ich würde versuchen, einen ganz anderen Ansatz zu finden. Warum möchtest du jeden Chunks in der x-Richtung um 1 nach X bewegen? Wenn du nur die dargestellte Position aller chunks verändern willst, brauchst du keinen Speicher zu bewegen. Dann kannst du eine globale, relative Position nutzen. In etwa:

C-/C++-Quelltext

1
2
3
4
5
Vector3 relativePosition(1.0f, 0, 0);
Vector3 GetGlobalChunkPosition(Chunk* pChunk)
{
    return pChunk->position + relativePosition;
}
EnvisionGame(); EnableGame(); AchieveGame(); - Visionen kann man viele haben. Sie umzusetzen und auf das Ergebnis stolz zu sein ist die eigentliche Kunst.

Werbeanzeige