[C++] Pointerdoolhof werkt niet

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Orwell
  • Registratie: December 2009
  • Laatst online: 08-09 22:11
Ben al een daagje of drie aan het proberen een centrale texturedump te maken voor m'n Engine. Dit zorgt ervoor dat elk model in de scene niet egoïstisch zijn eigen zooi bijhoudt, maar het van een aparte dump haalt. Hiervoor zijn gare constructies nodig:

Een array van structs, genaamd MODEL, waar in elke MODEL een pointer naar een struct genaamd TEXTURE zit, waarin weer een pointer naar een Direct3D-texture is te vinden.

Dit ziet er als het goed is zo uit:

C++:
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
// De textures
struct TEXTURE {
    LPDIRECT3DTEXTURE9 pointer;
    char name[MAX_PATH];
} textures[MAX_TEXTURES];

// De modellen
struct MODEL {
    // Model
    LPDIRECT3DVERTEXBUFFER9 vertexbuffer;
    LPDIRECT3DINDEXBUFFER9 indexbuffer;

    // Textures
    TEXTURE *diffusetex,*speculartex,*normaltex,*parallaxtex,*ambienttex;
    
    // Params
    float diffuse,specular,shininess;
    D3DXHANDLE shader;

    // Generic Data
    D3DXMATRIX worldpos;
    int numfaces,numverts,sortindex;
    float r;
} models[MAX_MODELS];

// En een denkbeeldige selectie
models[index].diffusetex->pointer;


Maar het werkt niet. De pointer en de naam waardes geven gaat perfect (geen segfaults ofzo), maar gebruiken van de pointer levert altijd een instantcrash op:
C++:
1
FX->SetTexture(FXSpeculartex,models[a].speculartex->pointer); // CRASH


Het opvullen van de items gaat overigens zo:
C++:
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
if(currentregel[0] == 's') {
    ssmat >> str >> texstr >> models[index].specular >> models[index].shininess;

    // Kijk of er al eentje in gebruik is
    bool reuse = false;
    for(int a = 0;a < numtextures;a++) {
        if(!strcmp(texstr,textures[a].name)) { // Als we deze al hebben
            models[index].speculartex = &textures[a];
            reuse = true;
            break;
        }
    }

    // Nee, een nieuwe
    if(!reuse) {
        if(texstr[1] != ':') { // DAN GEEN VOLLEDIG PAD
            sprintf(textemp,"%s\\Data\\Textures\\%s",exepath,texstr);
            D3DXCreateTextureFromFile(d3ddev,textemp,&textures[numtextures].pointer);
        } else {
            D3DXCreateTextureFromFile(d3ddev,texstr,&textures[numtextures].pointer);
        }
        strcpy(textures[numtextures].name,texstr);
        models[index].speculartex = &textures[numtextures];
        numtextures++;
    }
}


Maar gebruiken werkt zoals gezegd niet. Wat er wel zeker is:
  • De 3D-code zelf werkt perfect.
  • Ik ga niet over MAX_PATH (260), MAX_TEXTURES (1024) of MAX_MODELS (65536) heen.
  • Nalopen van de namen levert geen problemen op.
Heeft iemand een idee wat er aan de hand is?

Acties:
  • 0 Henk 'm!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

Gebruik een debugger, kijk naar de status van je arrays net voordat je crasht op die regel. Gewoon zelf kijken wat de waardes zijn.

Anders PIX gebruiken om te zien of je textures wel geldig zijn (geen errors eerder gehad)?

-niks-


Acties:
  • 0 Henk 'm!

  • NC83
  • Registratie: Juni 2007
  • Laatst online: 21-08 21:44
Zet je D3D runtime eens op debug libraries en zet de "Debug output level" op eentje onder het maximum, de D3D runtime zal je nu waarschuwingen laten zien waar performance bottlenecks zitten en waar je gewoon fouten hebt gemaakt in de debug output window.

ex-FE Programmer: CMR:DiRT2,DiRT 3, DiRT Showdown, GRID 2, Mad Max


Acties:
  • 0 Henk 'm!

  • Orwell
  • Registratie: December 2009
  • Laatst online: 08-09 22:11
MLM schreef op zaterdag 12 maart 2011 @ 15:19:
Gebruik een debugger, kijk naar de status van je arrays net voordat je crasht op die regel. Gewoon zelf kijken wat de waardes zijn.
De namen kloppen bijvoorbeeld perfect. Met dit:
C++:
1
2
for(int i = 0;i < numtextures;i++)
    Debug.log(textures[i].name,"NAME: ");

... krijgen we dit:

code:
1
2
3
4
5
6
7
NAME: sponza_thorn_diff.dds
NAME: BrickSpecular.dds
NAME: sponza_bricks_a_diff.dds
(...)
NAME: sponza_floor_a_spec.dds
NAME: sponza_column_c_diff.dds
NAME: Skybox_2.dds


Dat werkt dus. De textures zijn allemaal niet null (ze naar bool casten levert 'true' op). Op deze manier de pointer gebruiken levert overigens geen crash op.
Anders PIX gebruiken om te zien of je textures wel geldig zijn (geen errors eerder gehad)?
NC83 schreef op zaterdag 12 maart 2011 @ 15:51:
Zet je D3D runtime eens op debug libraries en zet de "Debug output level" op eentje onder het maximum, de D3D runtime zal je nu waarschuwingen laten zien waar performance bottlenecks zitten en waar je gewoon fouten hebt gemaakt in de debug output window.
Vergeten te melden. Die levert (met 4/5 zeikniveau) naast de deviceresetmeldingen niets op. Alleen iets over ongeveer 5 items die niet gereleased worden, maar dat is een ander probleem.

En uhm, als die pointer klopt werkt de 3D-code perfect. Geen twijfel mogelijk.



Goed, vreemd. De code die ik gebruikt heb als kopieërbron::

C++:
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
if(currentregel[0] == 'd') {
    ssmat >> str >> texstr >> models[index].diffuse;

    // Kijk of er al eentje in gebruik is
    bool reuse = false;
    for(int a = 0;a < numtextures;a++) {
        if(!strcmp(texstr,textures[a].name)) { // Als we deze al hebben
            models[index].diffusetex = &textures[a];
            reuse = true;
            break;
        }
    }

    // Nee, een nieuwe
    if(!reuse) {
        if(texstr[1] != ':') { // DAN GEEN VOLLEDIG PAD
            sprintf(textemp,"%s\\Data\\Textures\\%s",exepath,texstr);
            D3DXCreateTextureFromFile(d3ddev,textemp,&textures[numtextures].pointer);
        } else {
            D3DXCreateTextureFromFile(d3ddev,texstr,&textures[numtextures].pointer);
        }
        strcpy(textures[numtextures].name,texstr);
        models[index].diffusetex = &textures[numtextures];
        numtextures++;
    }
}


... werkt met (voor de volledigheid) ...

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void Renderer::passTechnique(SHADER curshader) {
    (...)
    for(allemodelleninbeeld) {
        (...)

        FX->SetFloat(FXMaterialdiffuse,models[a].diffuse);
        FX->SetFloat(FXMaterialspecular,models[a].specular);
        FX->SetFloat(FXMaterialshininess,models[a].shininess);
        FX->SetTexture(FXDiffusetex,models[a].diffusetex->pointer); // DEZE DOET HET WEL
        FX->SetTexture(FXSpeculartex,models[a].speculartex->pointer); // CRASH (van TS)
        // FX->SetTexture(FXNormaltex,models[a].normaltex->pointer);
        // FX->SetTexture(FXParallaxtex,models[a].parallaxtex->pointer);
        // FX->SetTexture(FXAmbienttex,models[a].ambienttex->pointer);

        (...)
        d3ddev->DrawIndexedPrimitive();
    }
    (...)
}


... wel. En dat is krom, want de code is compleet hetzelfde. Alleen de naam van de struct is anders. :?



De returncode van D3DXCreateTextureFromFile() is:
C++:
1
2
3
4
5
6
7
HRESULT hr = D3DXCreateTextureFromFile(d3ddev,textemp,&textures[numtextures].pointer);
switch(hr) {
    case D3D_OK: {
        MessageBox(hwnd,"'t Is allemaal gezegend!","Bericht",0);
        break;
    }
}


... en levert altijd op:

Afbeeldingslocatie: http://i56.tinypic.com/34e9w1t.png

Hoe langer ik er mee bezig ben, hoe waziger ik het vind worden. Er zit blijkbaar toch een fout in die pointerkronkel. De TEXTURE-structs zijn gewoon goed. :|

[ Voor 49% gewijzigd door Orwell op 12-03-2011 20:36 ]


Acties:
  • 0 Henk 'm!

  • 4VAlien
  • Registratie: November 2000
  • Laatst online: 24-06 09:47

4VAlien

Intarweb!

Ik zag in je eerste voorbeeld dat je in je struct &<D3Dpointer> deed, wat volgens mij op zichzelf ook al een pointer is. dan zit in je struct dus niet <D3Dpointer>* maar <D3Dpointer>** wat de crash kan verklaren. Of gebruiken alle texture vormen hier hetzelfde code path?

Acties:
  • 0 Henk 'm!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

Enige wat ik nog kan verzinnen is de strcpy op regel 22 die een texture pointer overschrijft als hij out-of-bounds gaat. En anders kan het gewoon in code zitten die ik niet kan zien.

Als je crash altijd op exact dezelfde texture zit kan je na het laden een data breakpoint zetten op de texture pointer om te zien of hij ooit overschreven word.

Heb je geen texture->Release() ergens staan die te vroeg gedaan word, of een device reset die niet je textures opnieuw aanmaakt (of je array niet update)?

-niks-


Acties:
  • 0 Henk 'm!

  • epic007
  • Registratie: Februari 2004
  • Laatst online: 25-08 11:27
Is een map gebruiken niet veel handiger ? http://www.cplusplus.com/reference/stl/map/operator[]/

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// accessing mapped values
#include <iostream>
#include <map>
#include <string>
using namespace std;

int main ()
{
  map<char,string> mymap;

  mymap['a']="an element";
  mymap['b']="another element";
  mymap['c']=mymap['b'];

  cout << "mymap['a'] is " << mymap['a'] << endl;
  cout << "mymap['b'] is " << mymap['b'] << endl;
  cout << "mymap['c'] is " << mymap['c'] << endl;
  cout << "mymap['d'] is " << mymap['d'] << endl;

  cout << "mymap now contains " << (int) mymap.size() << " elements." << endl;

  return 0;
}

Acties:
  • 0 Henk 'm!

  • Gehakt
  • Registratie: Juli 2002
  • Laatst online: 19-09 15:50
Is het geen mogelijkheid om valgrind (linux) te gebruiken om te zien waar het mis gaat met de pointers?

Acties:
  • 0 Henk 'm!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

Gehakt schreef op dinsdag 15 maart 2011 @ 11:03:
Is het geen mogelijkheid om valgrind (linux) te gebruiken om te zien waar het mis gaat met de pointers?
directX code draait meestal niet op linux :)

-niks-


Acties:
  • 0 Henk 'm!

  • Gehakt
  • Registratie: Juli 2002
  • Laatst online: 19-09 15:50
MLM schreef op dinsdag 15 maart 2011 @ 13:46:
[...]

directX code draait meestal niet op linux :)
Oh ja, ik zat weer eens niet op te letten :z

Acties:
  • 0 Henk 'm!

  • NC83
  • Registratie: Juni 2007
  • Laatst online: 21-08 21:44
MLM schreef op zondag 13 maart 2011 @ 14:48:
een device reset die niet je textures opnieuw aanmaakt (of je array niet update)?
Dat kan dus niet met D3DXCreateTextureFromFile aangezien je D3D_POOL dynamic is wat ervoor zorgt dat een device reset de resource opnieuw aan maakt.

Overigens kijkt je code nergens naar een array overschrijving wat rare gevolgen kan hebben.

Hier is een texture manager die ik al tijden gebruik, de texture hierin is niet veel meer dan een wrapper class om een IDirect3DTexture:
header texture manager
cpp texture manager

[ Voor 50% gewijzigd door NC83 op 16-03-2011 21:19 ]

ex-FE Programmer: CMR:DiRT2,DiRT 3, DiRT Showdown, GRID 2, Mad Max

Pagina: 1