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

FSA

Community-Fossil

  • »FSA« ist der Autor dieses Themas
  • Private Nachricht senden

1

27.07.2012, 22:30

Terrain: Meine Vertices wollen nicht

Ich programmiere gerade eine Terrainklasse die mit Heightmaps umgehen kann. Dazu lade ich ein Graustufenbitmap und lese die Farbe aus. Aus der Farbe ergibt sich die Höhe der Vertices.
Mein Problem liegt darin, dass nach einer Reihe an Dreiecken eine Linie von Rechts nach Links läuft. Das habe ich auf dem Bild "Vertices.bmp" veranschaulicht:
-Schwarze Linie zwischen den Vertices
-Rot die Linie, die vom Ende zum Anfang geht(recht->links). Am Ende der Roten Linie beginnt die nächste Reihe der Vertices.
-Goldenen Punkte: Vertices
Das ganze in echt ist in Bug.jpg zu finden.
Nach langem herum denken ist mir der Fehler klar geworden:
Ich nummeriere die Vertices von Links nach Rechts durch und fange am Ende der Zeile wieder Links an und eine Reihe tiefer. Das ergibt dann diese Linie. Aber ich weiß nicht wie ich ihn beheben kann.

Hier der Code wie ich mein Array erstelle, wo die Höhendaten drinnen stehen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
m_pHeightMap = new HeightMap[m_iTerrainWidth * m_iTerrainHeight];
    if(!m_pHeightMap)
    {
        return false;
    }

    k=0;
    index = 0;

    for(j = 0; j < m_iTerrainHeight; j++)
    {
        for(i = 0; i < m_iTerrainWidth; i++)
        {
            height = bitmapImage[k];

            m_pHeightMap[index].x = (float)i;
            m_pHeightMap[index].y = (float)height / fDivide;
            m_pHeightMap[index].z = (float)j;
            index++;

            k += 3;
        }
    }

In bitmapImage stehen die Farben drinnen.

Hier der Code zum Generiern des Vertex und Indexbuffers:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
Vertex vertex;
    m_pVertexBuffer = new VertexBuffer;
    m_pIndexBuffer = new IndexBuffer;

    m_iVertexCount = (m_iTerrainHeight) * (m_iTerrainWidth);
    m_iIndexCount =(m_iTerrainHeight - 1) * (m_iTerrainWidth - 1) * 6;

    // VertexBuffer
    if(m_pVertexBuffer->Init(m_iVertexCount * sizeof(Vertex), sizeof(Vertex), Vertex::dwFVF))
        return false;

    int index = 0;

    for(int j = 0; j < m_iTerrainHeight; j++)
    {
        for(int i = 0; i < m_iTerrainWidth; i++)
        {
            Vector3 vPosition;
            vPosition.x = ((float)(i) / (float)(m_iTerrainWidth - 1) - 0.5f) * (float)m_iTerrainWidth;
            vPosition.y = m_pHeightMap[index].y / 10.0f;
            vPosition.z = ((float)(-j) / (float)(m_iTerrainHeight - 1) + 0.5f) * (float)m_iTerrainHeight;

            vertex.Position = vPosition;
            vertex.tex = Vector2Random();

            m_pVertexBuffer->SetVertex(GetVertexIndex(i, j, m_iTerrainWidth), &vertex);
            index++;
        }
    }

    // Aktualisieren
    if(m_pVertexBuffer->Update()) return false;


    // IndexBuffer
    m_pIndexBuffer = new IndexBuffer;
    if(m_pIndexBuffer->Init(m_iIndexCount * sizeof(WORD), sizeof(WORD), D3DFMT_INDEX16))
        return false;

    for(int j = 0; j < m_iTerrainHeight; j++)
    {
        for(int i = 0; i < m_iTerrainWidth; i++)
        {
            WORD wIndex;
            wIndex = GetVertexIndex(i, j, m_iTerrainHeight);            m_pIndexBuffer->AddIndex(&wIndex);
            wIndex = GetVertexIndex(i + 1, j, m_iTerrainHeight);        m_pIndexBuffer->AddIndex(&wIndex);
            wIndex = GetVertexIndex(i, j + 1, m_iTerrainHeight);        m_pIndexBuffer->AddIndex(&wIndex);

            wIndex = GetVertexIndex(i, j + 1, m_iTerrainHeight);        m_pIndexBuffer->AddIndex(&wIndex);
            wIndex = GetVertexIndex(i + 1, j, m_iTerrainHeight);        m_pIndexBuffer->AddIndex(&wIndex);
            wIndex = GetVertexIndex(i + 1, j + 1, m_iTerrainHeight);    m_pIndexBuffer->AddIndex(&wIndex);
        }
    }

    // Aktualiesieren
    if(m_pIndexBuffer->Update()) return false;


GetVertexIndex:

C-/C++-Quelltext

1
2
3
4
WORD GetVertexIndex(WORD x, WORD y, int iSize)
{
    return y * iSize + x;
}


Die Heightmap hat gleiche Höhe/Breite.

Das Problem ist leicht zu finden, aber wie gesagt ich weiß keine Lösung...

Danke für jegliche Hilfe.

EDIT: Mit dem Vertices-Bild ist wohl was schief gelaufen ?(
»FSA« hat folgendes Bild angehängt:
  • Bug.jpg
»FSA« hat folgende Datei angehängt:
  • Vertices.bmp (196,66 kB - 54 mal heruntergeladen - zuletzt: 19.03.2024, 06:21)

Zitat

Der RCCSWU (RandomCamelCaseSomtimesWithUndersquare) Stil bricht auch mal mit den veraltet strukturierten Denkmustern und erlaubt dem Entwickler seine Kreativität zu entfalten.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »FSA« (27.07.2012, 23:20)


idontknow

unregistriert

2

28.07.2012, 01:07

Zitat

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
for(int j = 0; j < m_iTerrainHeight; j++)
    {
        for(int i = 0; i < m_iTerrainWidth; i++)
        {
            Vector3 vPosition;
            vPosition.x = ((float)(i) / (float)(m_iTerrainWidth - 1) - 0.5f) * (float)m_iTerrainWidth;
            vPosition.y = m_pHeightMap[index].y / 10.0f;
            vPosition.z = ((float)(-j) / (float)(m_iTerrainHeight - 1) + 0.5f) * (float)m_iTerrainHeight;

            vertex.Position = vPosition;
            vertex.tex = Vector2Random();

            m_pVertexBuffer->SetVertex(GetVertexIndex(i, j, m_iTerrainWidth), &vertex);
            index++;
        }
    }


Vorweg erstmal raff ich die Berechnung deiner x/z Koordinaten überhaupt nicht. Erkläre mir mal bitte was du damit erreichen willst. Aber das ist nicht das einzige woran es happert.
Angenommen wir haben ein Terrain mit Größe 2x2, also 4 Dreiecke. Dann brauchst du insgesamt 3*3 Vertices, mit deiner Schleife gibdts aber nur 4 außer du hast TerrainHeight/Width inkrementiert.
Das ist so was mir direkt auffällt. Ansonsten würde ich die Vertices eher lokal in ein Array packen anstatt sie einzeln in den Buffer zu schreiben weils erstens schneller ist und du das Array (std::vector..) viel besser debuggen kannst.

Noch was: wie du schon gemerkt hast stimmen deine Indizes nicht, allerdings vermutlich nicht nur die die von denen du weißt, dass sie nicht stimmen. Wie hast du den Buffer erstellt bzw. mit welcher Größe? Immerhin sollte

C-/C++-Quelltext

1
wIndex = GetVertexIndex(i + 1, j + 1, m_iTerrainHeight); 

nicht mehr so rund laufen, wenn i bzw j den Wert Width/Height - 1 im letzten Durchlauf erreicht haben. Wie du bereits erkannt hast haben alle deine Indizes einen Fehler wenn i den Wert Width - 1 hat, dann wird i zu Width und da du eigentlich nur 0-Width-1 Vertices pro Zeile hast landest du in der nächsten Zeile. Das gleiche Problem eigentlich auch bei der letzten Zeile. Wenn ich da nicht einen Denkfehler drin habe frage ich mich warum das überhaupt ausgeführt wird oO

Um das ganze zu beheben musst du dir was anderes einfallen lassen zum berechnen der Indizes, am besten zeichnest du dir einfach mal ein Minifeld mit z.b. 9 Vertices auf (weniger ist bisschewitzlos) und gehst deinen Algorithmus durch um Fehler zu erkenen bzw. findest einen neuen. Einfach so ne Lösung geben wäre ja langweilig ;).

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »idontknow« (28.07.2012, 01:33)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

3

28.07.2012, 08:18

"Aktualisieren" enthält nur 2mal e, nicht 3mal. Ich weiß, pingelig, aber das hast Du schon letztens irgendwo geschrieben, FSA, es muss jetzt einfach mal korrigiert werden. Mal davon abgesehen, braucht man bei einer Methode, die Update heißt, bestimmt keinen solchen Kommentar ;)
Ansonsten hat idontknow ja schon alles wichtige gesagt: i+1, j+1 ist ein Zugriff auf Dir nicht gehörenden Speicher im letzten Durchlauf und die Berechnung der Koordinaten x und y ist etwas unklar.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

4

28.07.2012, 09:51

Hab mal wieder die Zensurliste erweitert :D

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

5

28.07.2012, 10:08

Sehr gut :D
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

FSA

Community-Fossil

  • »FSA« ist der Autor dieses Themas
  • Private Nachricht senden

6

28.07.2012, 11:56

@idontknow: Danke für deine Erklärung. Tatsächlich musste ich beim Erstellen der Indices Terrain width und height inkrementieren.

@BC: Ich habe immer meine Probleme mit Aktualisieren, Initialisieren und Co...

Also Problem ist behoben. Jetzt werde ich alles noch in ein Array schreiben, anstatt einzelne zu übergeben.

Danke für die Hilfe. 8)

Zitat

Der RCCSWU (RandomCamelCaseSomtimesWithUndersquare) Stil bricht auch mal mit den veraltet strukturierten Denkmustern und erlaubt dem Entwickler seine Kreativität zu entfalten.

idontknow

unregistriert

7

28.07.2012, 13:00

Kannst ja mal deine Berechnung der Indizes dann noch posten (unter anderem auch für Leute die ein ähnliches Problem haben ich selber hab z.b. genau den selben Fehler wie du gemacht bei meinem ersten Terran (und zwar exakt, mit 1 Vertex zu wenig aus dem Speicher rauschreiben und die falsche Berechnung der Indizes)

Würde mich außerdem interessieren wie du es dann letztlich gelöst hast gibt da bestimmt sehr viele Wege.

FSA

Community-Fossil

  • »FSA« ist der Autor dieses Themas
  • Private Nachricht senden

8

31.07.2012, 09:48

Tschuldige ich meinte natürlich dekrementieren.
Ich kann erst nächste Woche Posten, da ich noch nicht am Heimrechner bin.

Zitat

Der RCCSWU (RandomCamelCaseSomtimesWithUndersquare) Stil bricht auch mal mit den veraltet strukturierten Denkmustern und erlaubt dem Entwickler seine Kreativität zu entfalten.

FSA

Community-Fossil

  • »FSA« ist der Autor dieses Themas
  • Private Nachricht senden

9

07.08.2012, 20:41

Also dann Urlaub ist fertig. Hier der Code für die Indices:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// IndexBuffer
    m_pIndexBuffer = new IndexBuffer;
    if(m_pIndexBuffer->Init(m_iIndexCount * sizeof(long), sizeof(long), D3DFMT_INDEX32))
        return false;

    for(int j = 0; j < m_iTerrainHeight - 1; j++)
    {
        for(int i = 0; i < m_iTerrainWidth - 1; i++)
        {
            long wIndex;
            wIndex = GetVertexIndex(i, j, m_iTerrainHeight);            m_pIndexBuffer->AddIndex(&wIndex);
            wIndex = GetVertexIndex(i + 1, j, m_iTerrainHeight);        m_pIndexBuffer->AddIndex(&wIndex);
            wIndex = GetVertexIndex(i, j + 1, m_iTerrainHeight);        m_pIndexBuffer->AddIndex(&wIndex);

            wIndex = GetVertexIndex(i, j + 1, m_iTerrainHeight);        m_pIndexBuffer->AddIndex(&wIndex);
            wIndex = GetVertexIndex(i + 1, j, m_iTerrainHeight);        m_pIndexBuffer->AddIndex(&wIndex);
            wIndex = GetVertexIndex(i + 1, j + 1, m_iTerrainHeight);    m_pIndexBuffer->AddIndex(&wIndex);
        }
    }

Zitat

Der RCCSWU (RandomCamelCaseSomtimesWithUndersquare) Stil bricht auch mal mit den veraltet strukturierten Denkmustern und erlaubt dem Entwickler seine Kreativität zu entfalten.

Werbeanzeige