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

Snorky

Frischling

  • »Snorky« ist der Autor dieses Themas

Beiträge: 34

Wohnort: Berlin

Beruf: Student

  • Private Nachricht senden

1

13.08.2003, 18:49

Texturmanager mit kleinem Fehler

Nach mehrmaligem durcharbeiten des Buches und die ersten kleineren Programmierversuche mit der Engine (die mir im übrigen persönlich recht gut gefällt :biggrinlove: ) bin ich auf ein kleines Problem im Texturmanager gestoßen:

Wenn man den Texturmanager startet, wieder herunterfährt und dann ein weiteres mal startet bricht das Programm mit einem kritischen Fehler ab.

Ja, wer startet schon den Texturmanager ein weiteres mal? :huhu:

Das Problem liegt daran, dass tbMemFree() den void-Pointer nach Freigabe des Speichers nicht selbst auf NULL setzt. Von größeren Änderungen der Engine möchte ich lieber absehen, denn wer weiß (außer David vielleicht), was das für Folgebrobleme mit sich bringen könnte.
Als Ansatz könnte man aus dem Parameter einen Referenzpointer à la tbResult tbMemFree(void*& pMemory); machen und dann auf NULL setzen, allerdings gabs dann Probleme in der tbGUI mit dem Makro TB_SAFE_MEMFREE und ganz ansi-mäßig ist das sicher auch nicht.

Ok, also zur Ersatz-Lösung:
Das eigentliche Problem über das ich gestolpert bin, ist dass in der Exit()-Funktion der Pointer m_pTexturList immernoch in den Speicher zeigt, obwohl er nach dem freigeben aller Texturen auf NULL zeigen sollte. Also gehen wir in der tbTextureManager.cpp in die DeleteAllTextures() und vervollständigen am Ende:

// Die ganze Liste löschen
tbMemFree(m_pTextureList);
m_pTextureList = NULL;
m_iListSize = 0;
m_iNumTextures = 0;

Das sollte dieses kleine Problem beheben, über das sowieso niemand weiteres stolpern wird ;)


Aber wenn wir schon mal dabei sind in der tbTextureManager.cpp rumzupfuschen...
Mir ist aufgefallen, dass beim laden einer Textur in der Struktur tbTextureListEntry die Werte für die Höhe, Breite und Tiefe der Textur nicht gespeichert werden, wenn wir als Parameter D3DX_DEFAULT verwenden. Ob das so sein soll && / || einen tieferen Sinn hat, weiss ich nicht, allerdings benötigte ich diese Informationen und ich bin mir relativ sicher, dass ich in diesem Fall nicht alleine dastehen sollte. Also hier die Änderungen:

In der Funktion LoadTexture(tbVFile* pVFile,...) folgende Zeilen vor dem Label TryAgain einfügen:
D3DXIMAGE_INFO imageInfo;
ZeroMemory(&imageInfo, sizeof(imageInfo));

Und folgende nach dem if(D3DXCreateTextureFromFileInMemoryEx)-Block, also vor AddTextureToList():
// tatsächliche Bilddimensionen ermitteln
iHeight = imageInfo.Height;
iWidth = imageInfo.Width;

Damit die imageInfo-Daten auch gefüllt werden muss er natürlich auch als vor-vor-letzter Parameter in D3DXCreateTextureFromFileInMemoryEx() eingefügt werden, also so:
D3DXCreateTextureFromFileInMemoryEx(tbDirect3D::GetDevice(), &(((BYTE*)(pVFile->GetBuffer()))[pVFile->GetCursor()]), pVFile->GetSize() - pVFile->GetCursor(), iWidth, iHeight, iNumMIPLevels, dwUsage, Format, Pool, dwFilter, dwMIPFilter, ColorKey, &imageInfo, NULL, &pTexture)

Diese Änderungen sollte man jetzt auch noch in LoadCubeTexture() und LoadVolumeTexture() vornehmen.

Bei der kubischen Textur reicht die Info einer Seite:
// tatsächliche Bilddimensionen ermitteln
iSize = imageInfo.Height;

Und bei der volumiösen ist die Tiefe auch recht interessant:
// tatsächliche Bilddimensionen ermitteln
iHeight = imageInfo.Height;
iWidth = imageInfo.Width;
iDepth = imageInfo.Depth;


Soviel dazu, ich hoffe das hilft weiter.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

14.08.2003, 01:24

Hi!
Guter Beitrag! Das mit dem Texturmanager habe ich jetzt behoben.
Dass nicht die tatsächliche Breite/Höhe/Tiefe gespeichert wird, hat schon seinen Grund. Denn der Texturmanager verwendet diese Angaben ja, um zu prüfen, ob eine Textur schon geladen wurde oder nicht.
Wenn ich D3DX_DEFAULT bei Breite/Höhe/Tiefe angebe, es wird aber tatsächlich etwas anderes in die Liste eingetragen, dann wird der Texturmanager beim nächsten Laden der Textur ebenfalls mit D3DX_DEFAULT denken, dass es die Textur noch garnicht im Speicher gibt, und er wird sie erneut laden.
Aber die Breite/Höhe/Tiefe einer Textur abzufragen ist ja nicht viel Arbeit - zwei simple Zeilen:

D3DSURFACE_DESC Desc;
pTexture->GetLevelDesc(0, &Desc);

Dann hast Du in Desc.Width und Desc.Height schon die Breite und die Höhe der Textur. Da das so schnell geht, dachte ich, es wäre eigentlich nicht notwendig, die tatsächliche Breite/Höhe/Tiefe noch mitzuspeichern. Mal davon abgesehen, dass der Texturmanager ja sowieso keinen Zugriff auf die tbTextureListEntry-Strukturen liefert, sondern nur für die Beschaffung der IDirect3D(Cube/Volume)Texture9-Zeiger zuständig ist.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

3

14.08.2003, 12:20

Bitte auch folgende Topics beachten:
http://www.scherfgen-software.net/forum/viewtopic.php?t=744
http://www.scherfgen-software.net/forum/viewtopic.php?t=751

Werbeanzeige