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

1

05.06.2004, 20:11

Fehler beim kopieren von Speicherbereichen

Ich programmiere mir gerade einen 3D modelleditor. Nur leider macht die Exportfunktion schwierigkeiten:

Quellcode

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
57
58
59
60
61
62
63
void CPartlist::ExportToFile(LPCSTR Filename)
{
    //Als erstes die Gesamtzahl der Vertices/Indices ermitteln
    int iNumVertices=0;
    int iNumIndices=0;
    m_PartIt=m_Partliste.begin();
    for(int i=0; i<m_Partliste.size(); i++)
    {
        iNumVertices+=(*m_PartIt)->GetNumVertices();
        iNumIndices+=(*m_PartIt)->GetNumIndices();
        m_PartIt++;
    }
    //Jetzt entsprechene Speicher reservieren, die V und I kopieren und in eine SDatei schreiben!
    TexturedVertex* Vertices=new TexturedVertex[iNumVertices];
    TexturedVertex* pVertices=Vertices;//Schreibcursor für die Schleife
    

    //Aus vielen kleinen Vertexfelder ein großes machen:

    unsigned short* Indices=new unsigned short[iNumIndices];
    unsigned short* pIndices=Indices;//s. o.

    //Jetzt in einer Schleiffe alle VertexDaten in Vertices kopeiren
    int iTempNumIndices=0;
    m_PartIt=m_Partliste.begin();
    for(i=0; i<m_Partliste.size(); i++)
    {
        memcpy(pVertices, (*m_PartIt)->GetVertices(), sizeof(TexturedVertex)*(*m_PartIt)->GetNumVertices());
        pVertices+=(*m_PartIt)->GetNumVertices();

        memcpy(pIndices, (*m_PartIt)->GetIndices(), sizeof(unsigned short)*(*m_PartIt)->GetNumIndices());
        //Die Indices sind ja alle relativ, Dehalb müssen sie alle hochgezählt werden
        
        for(int i2=0; i<(*m_PartIt)->GetNumIndices(); i++)
        {
            pIndices[i2]+=iTempNumIndices;
        }
        iTempNumIndices+=(*m_PartIt)->GetNumVertices();

        pIndices+=(*m_PartIt)->GetNumIndices();//Den Schreibcursor weiter setzten

        m_PartIt++;
    }

    //Jetzt alle Vertices und Indices in die Datei schreiben
    char cDateiname[16], cTexturname[16];
    sprintf(cTexturname, "default.png");
    sprintf(cDateiname, "%s.c3m", Filename);
    FILE* Datei=fopen(cDateiname, "w");

    fwrite(&iNumVertices, sizeof(int), 1, Datei);
    fwrite(Vertices, sizeof(TexturedVertex), iNumVertices, Datei);

    fwrite(&iNumIndices, sizeof(int), 1, Datei);
    fwrite(Indices, sizeof(unsigned short), iNumIndices, Datei);

    fwrite(cTexturname, sizeof(char), 16, Datei);
    fclose(Datei);

    //Den temporären Speicher wieder freigeben
    delete[] Vertices;
    delete[] Indices;
}


Wenn ich die ein Modell exportiere, und anschließend verscuh zu laden, stimmen die Daten nicht mehr. Komischerweise sind die Vertexdaten bis zu einem bestimmetne Punkt richtig, danach enthalten sie nur noch Quatsch. Bei den Indexdaten ist es genau das selbe.
Der Texturname kann allerdings fehlerfrei gelesen weden.
Es scheint also so, als ob die Schleife, die die Speicherbereich zusammenkopieren soll, bei den ersten 2 Durchgängen funktioniert und ab dann nicht mehr. Hat jemand ne Ahnung woran das liegen könnte?

Wie man sehen kann, hab ich versucht für den neuen Speicherbereich so ne Art Schreibcursor zu benutzen. Gerade bei einem Test, konnte er die erste Gruppe problemlos schreiben, bei der 2 waren alle Werte nur noch Blödsinn. Liegt es also evtl. am Schreibcursor?

Till

Alter Hase

Beiträge: 378

Wohnort: Lincoln College, Oxford

Beruf: Student

  • Private Nachricht senden

2

05.06.2004, 21:27

Hmmm...deine Daten stimmen also vor dem Kopieren in das dynamische Array auf jeden Fall, oder?
Öffne doch die Datei mit dem "binary"-Attribut ("wb"), doch ich weiß nicht, ob das was hilft.

Aber: schön, STL-Container und Iteratoren sieht man hier selten! :)
DOMINVS ILLVMINATIO MEA
---
Es lebe unmanaged Code!
---
>> Meine Uni <<

3

05.06.2004, 23:11

das mit dem "wb" hilft wahrscheinlich nichts. Hab ich noch nie gemacht. ich hab auch schon an anderer Stelle ein dynamisch Array in ne Datei geschrieben, ging auch. Ich denke mal, das es an dem Zeiger liegt. Ich hab ja versucht den mit dem "+=" weiter zu setzten, aber bin mir halt nicht siicher, ob das so funzt. Wenn man einen Zeiger mit ++ erhöht, zeigt er doch immer auf das nächste Element, oder? (Wird also um die Größe des Typs auf den er zeigt erhöht). Dann müsste meine Schreibweise doch auch funktioniern.
Die Daten in den der STL Liste stimmen 100%, ich arbeite ja die ganze zZeit mit ihnen und zeig sie auch an.
Sollte ich vieleicht einen anderen Ansatz wählen? Wie würdet ihr den die Speicherbereiche zusammenkopieren?

Und: Von mir aus kann ich noch jede Menge STL-Code posten, benutz ich dauernd. Ich versteh gar nicht warum David in der TriBase Engine so die STL-Liste nachmacht. Ich hab jedenfalls so was ähnliches gefunden.

Osram

Alter Hase

Beiträge: 889

Wohnort: Weissenthurm

Beruf: SW Entwickler

  • Private Nachricht senden

4

05.06.2004, 23:44

Zitat


das mit dem "wb" hilft wahrscheinlich nichts. Hab ich noch nie gemacht.


Dann hast Du's immer falsch gemacht. In eine ohne "b" geöffnete Datei kannst Du z.B. mit "printf" reinschreiben, aber Du darfst Sie nicht als binäre Datei benutzen.

Zitat


Ich hab ja versucht den mit dem "+=" weiter zu setzten, aber bin mir halt nicht siicher, ob das so funzt. Wenn man einen Zeiger mit ++ erhöht, zeigt er doch immer auf das nächste Element, oder? (Wird also um die Größe des Typs auf den er zeigt erhöht). Dann müsste meine Schreibweise doch auch funktioniern.


Ja, das ist richtig.
"Games are algorithmic entertainment."

5

06.06.2004, 23:24

ok ich hab "wb" mal ausprobiert, aber es hat nix gebracht. Ich bin mir eigentlich sicher, das das Problem nicht im schreiben in die Datei liegt, sondern beim zusammenkopieren der Speicherbereiche. Ich schätze mal, da ist irgend ein saublöder Fehler drin, den man nur Übersieht. Vieleicht wär es ne Lösung die Funktion zu löschen und komplett neu zu schreiben.
Aber wie würdet ihr das denn realiseren, verschiedene Speicherbereiche zusammen zu kopieren? Ich hab ja von jedem Teilbereich einen Zeiger und die Größe. Hat jemand vielciht noch nen besseren Ansatz?

adapto

Treue Seele

Beiträge: 147

Wohnort: Berlin

Beruf: Student

  • Private Nachricht senden

6

07.06.2004, 02:08

Quellcode

1
fwrite(&iNumVertices, sizeof(int), 1, Datei);

na ob das mal stimmt?

size_t fwrite(
const void *buffer,
size_t size,
size_t count,
FILE *stream
);

Quellcode

1
fwrite(&pVertices, iNumVertices,1,Datei);


wenn ich das auf die schnelle richtig sehe...

7

07.06.2004, 12:32

Jo, das müste stimmen, da der erste size parameter die Größe in Byte braucht, und der 2 die Anzhal der Schribvorgänge.
ich hätte auch schreiben können:
sizeof(TexturedVertex)*iNumVertices, 1
aber das würde ja den Sinn des zweiten Parameters verfälschen. Außerdem hab ich das sonst auch so gemacht, und da funktionierts auch.

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

8

07.06.2004, 14:03

Warum willst du das eigendlich zusammen kopieren ??? Man kann jeden vertex mit ner schleife einfach dran hängen......

9

07.06.2004, 15:15

@Nox
Genau das wollte ich hören!
Ist wircklich tausendmal einfacher und verschwendet nicht so viel Speicehr. Also statt erst alles in ne neue Variable zu kopieren in der Schleife direkt alles in die Datei schreiben. Kling vernünftig und einfacher. Ich werfds gleich mal ausprobieren.
thx a lot!

10

15.06.2004, 20:30

So die neue Funktion sieht so aus:

Quellcode

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
57
58
59
60
61
62
63
64
65
66
67
void CPartlist::ExportToFile(LPCSTR Filename)
{
    //Als erstes die Gesamtzahl der Vertices/Indices ermitteln
    int iNumVertices=0;
    int iNumIndices=0;
    m_PartIt=m_Partliste.begin();

    for(int i=0; i<m_Partliste.size(); i++)//Schleife durchgehen und Teilzahlen zu Gesamtzahl addieren
    {
        iNumVertices+=(*m_PartIt)->GetNumVertices();
        iNumIndices+=(*m_PartIt)->GetNumIndices();
        m_PartIt++;
    }

    //Jetzt alle Vertices und Indices in die Datei schreiben

    //Datei öffnen
    char cDateiname[16];
    sprintf(cDateiname, "%s.mdl", Filename);
    FILE* Datei=fopen(cDateiname, "wb");//fehlt: Wenn Datei nicht geöffnet werden konnte...

    
    
    //Alle Vertices speichern
    fwrite(&iNumVertices, sizeof(int), 1, Datei);
    m_PartIt=m_Partliste.begin();
    for(i=0; i<m_Partliste.size(); i++)
    {
        fwrite((*m_PartIt)->GetVertices(), sizeof(TexturedVertex), (*m_PartIt)->GetNumVertices(), Datei);
        m_PartIt++;
    }

    //alle Indices speichern
    fwrite(&iNumIndices, sizeof(int), 1, Datei);

    int iTempNumIndices=0;
    unsigned short *pIndices=NULL, *pIndex=NULL;
    m_PartIt=m_Partliste.begin();
    for(i=0; i<m_Partliste.size(); i++)
    {
        //Die Indices müssen noch umgerechnet werden!
        pIndices=new unsigned short[(*m_PartIt)->GetNumIndices()];
        if(NULL==pIndices)
        {
            Error("Kein Speicher vorhanden");
        }
        pIndex=(*m_PartIt)->GetIndices();

        //Die Indexdaten kopieren und umrechnen
        for(int i2=0; i2<(*m_PartIt)->GetNumIndices(); i2++)
        {
            pIndices[i2]=pIndex[i2];
        }
        for(i2=0; i2<(*m_PartIt)->GetNumIndices(); i2++)
        {
            pIndices[i2]+=(unsigned short)iTempNumIndices;
        }
        iTempNumIndices+=(*m_PartIt)->GetNumVertices();

        fwrite(pIndices, sizeof(unsigned short), (*m_PartIt)->GetNumIndices(), Datei);
        delete[] pIndices;
        pIndices=NULL;
        m_PartIt++;
    }
    fwrite(m_acTexturename, sizeof(char), 16, Datei);
    fclose(Datei);
}


Das problem ist das umrechnen der Indices. Dasa funktioniert zwar meistens, aber irgendwie nicht immer. Seltsamerweise gehts es nicht merh korrekt, wenn das Modell zu komplex-groß ist. Dann wird ab etwa 3/4 der indexliste nix mehr richtig gespeichert. Auch der Texturname wird nicht richtig geseichert, das heißt, wahrscheinlich nur nicht an der richtigen Stelle.
Bei kleineren Modellen geht alles gut. Wenn ich die Addition von iTempNumIndices weglasse, gehts auch bei komplexeren Modellen. Woran kann das liegen??? Es muss ja irgendetwas mit dem schreiben in die Datei zu tin haben, oder?
Achja, die komplexeren Modelle haben auch alle insgesamt <100 <Vertices und <100 Indices. Kann also eigentlich kein Variablenüberlauf oder so sein.

Werbeanzeige