Registriert: Mi Jan 31, 2007 18:32 Beiträge: 150
Programmiersprache: Pascal
ich habe versucht einen eigenen 3DS loader zu schreiben....habe aber festgestellt das die procedure zu einem zu frühen Zeitpunkt verlassen wird, kann mir aber nicht erklären warum
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Bitte solche riesen Codestücke nicht in die Beiträge einfügen. Dadurch leidet nur die Übersicht. Da es sich um eine ganze Unit handelt lieber die Unit als zip packen und anhängen. Du kannst deinen Beitrag auch nachträglich noch bearbeiten und die Unit anhängen. Danke.
Registriert: Mi Jan 31, 2007 18:32 Beiträge: 150
Programmiersprache: Pascal
Das ist jetzt sehr ungünstig ... ich hab (dummerweise) den code einer Unit eingefügt und zu diesem noch aus anderen Units code hinzugefügt um nicht alle verwendeten Units hochzuladen .... somit hatte ich allen meiner meinung nach relevanten Code zusammen im vohrigen Beitrag und kann jetzt den Code wieder neu zusammensuchen...
Registriert: Di Jul 01, 2003 18:59 Beiträge: 887 Wohnort: (The Netherlands)
Programmiersprache: fpc/delphi/java/c#
The download does not seem to work for me. So i cannot test it but:
Do you properly initialize: Result.Meshs[MeshCount - 1] ?
Also try Result := Localvar;
Or rewrite it to avoid the use of Result. E.g. make it a loaderclass.
The 3ds format is not easiest fileformat on the planet. My 3ds loader is largely complete, but still has room for improvement (http://www.noeska.com/dogl/gl3ds.aspx).
Registriert: Mi Jan 31, 2007 18:32 Beiträge: 150
Programmiersprache: Pascal
I also tryed this but doesn't work... the error is just at an other position I checked the with the debugger if there is a reason, but MeshCount has a correct value....
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Okay. Ich hätte nicht erwartet, dass das deine einzige Kopie ist. Aber um mich zu verteidigen. Hätte ich es nicht entfernt hätte es sicher jemand anders gemacht. Ich war nur schneller.
Nichts desto trotz habe ich den Code noch und habe gerade mal verglichen. Der einzige Unterschied besteht darin, dass die letzte große Schleife (Zeile 528) auskommentiert ist. Solltest du ihn benötigen kann ich ihn dir auch noch mal zukommen lassen.
Registriert: Mi Jan 31, 2007 18:32 Beiträge: 150
Programmiersprache: Pascal
schon gut ,dass das der einzige unterschied ist leigt darin das ich alles neu rausgesuch und dann gemerkt haben das der letzte Teil auskopmmentiert werden sollte da dieser weder fertig noch 1mal durchgelaufen ist....
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Result ist vergleichbar wie eine lokale Variable. Dessen Speicher ist nicht initialisiert. Das sieht man sehr schön, wenn man in TModelData ein zusätzliches Feld wie "Test2: array[0..99] of Integer;" einbringt. Dort stehen nur willenlose Zahlen drinne. Aber anscheinend macht er bei dynamischen Arrays ein Spezialhandling.
Wenn du ein dynamisches Array mit SetLength erweiterst wird der Speicher aber auf 0 initialisiert. Von daher dürfte die Initialisierungsthematik eher nicht zum tragen kommen, da dein Hauptrecord nur aus 2 dynamischen Arrays besteht.
Aber ich könnte mir fast vorstellen, dass es da mit den Records und den dynamischen Arrays zu Problemen kommen kann. Denn du arbeitest eigentlich nur mit dynamischen Arrays und Records. Das sollte eigentlich keine Probleme machen aber ich meine schön öfter mal erlebt zu haben, dass eine übermäßige Benutzung/Verschachtelung davon zu Problemen führt. Denn intern muss beim Erweitern Speicher kopiert werden und er muss sich merken auf welche Dinge wie und wo zugegriffen wird. Und da könnte es sein, dass Delphi durcheinander kommen kann. Ich meine mich zu mindest an so etwas zu erinnern. Ich selbst verwende solche Konstrukte eher nicht (zu mindest nicht so komplex) weswegen ich jetzt keinen direkten Fall habe wo so etwas passiert ist.
Ich würde aber auch eher das vorschlagen was noeska schon erwähnt hatte. Also eine Struktur auf Klassenbasis mit Listen von Meshs die auch wieder Klassen wären. Das würde außerdem auch dafür sorgen, dass intern nicht so viel Speicher hin und her kopiert werden muss.
Im Zweifel würde ich dir in jedem Fall empfehlen die Bereichsprüfung, die Überlaufprüfung und die I/O Prüfung zu aktivieren. Evtl kann es auch sein, dass du zufällig mal über die Grenzen eines Arrays hinwegschreibst was durch die Bereichsprüfung eigentlich überprüft werden sollte. Das ergäbe dann Exceptions und du wüsstest, dass irgendwas falsch ist. Dann eigentlich auch wo es Falsch läuft.
Ich kann es aber nicht Testen und 3DS ist auch nicht mein Spezialgebiet. Im Code hatte ich aber zu mindest keine groben/auffälligen Auffälligkeiten entdeckt. Wobei mir da gerade was auffällt, was durchaus hässlich enden kann.
Und zwar verlangt Stream.Read/Write als ersten Parameter grundsätzlich IMMER einen Datenbuffer. Denn diese Methoden bekommen durch das das const/var der Parameter immer nur den Pointer auf den Speicher übergeben. Bei Integer ist das okay. Bei Pointern (Strings und dyn arrays sind auch pointer) musst du aber explizit die erste Stelle des Speichers angeben. Denn sonst bekommt die Methode nur den Pointer deiner Pointervariable übergeben. Also im Falles des obrigen Beispieles bekommt Read nicht den mit GetMem erstellten Speicher sondern die Variable Vertices übergeben. Da Vertices normal massiv Daten enthalten denke ich wird er dir einiges deiner Strukturen überschreiben. Deswegen musst du an diesen Stellen IMMER expliziet dereferenzieren. Bei Dyn Array musst du auch immer die erste Arraystelle angeben [0]. Bei Strings das erste Zeichen [1]. Denn sonst würde er dir wieder anderen Speicher überschreiben.
Bei den TexCoords genau das Gleiche. Der Rest sollte aber gehen.
Außerdem sind die Farben als 4f deklariert aber du ließt nur 3f ein. Da solltest du sicher stellen, dass die der Alphawert auch initalisiert wird, denn ansonsten steht der durch die Initialisierung auf 0.
Registriert: Mi Jan 31, 2007 18:32 Beiträge: 150
Programmiersprache: Pascal
Zitat:
Da Vertices normal massiv Daten enthalten denke ich wird er dir einiges deiner Strukturen überschreiben
Diese Problem ist bisher noch nicht aufgetreten... das ganze hatte auch bis auf angesprochenes Problem funktioniert ... heist ich konnte alle Vertices als Punkte darstellen soweit ich das beuteilen kann hat auch keiner gefehlt(ich habe das Model welches ich zum testen benutze selber gemacht) Frage wenn ich mit getmem Speicher resaviere zeigt der Pointer nicht automatisch auf den Anfang des entsprechenden Speichers.. und wenn ich dann bei AStream.Read die anzahl Bytes angebe wird dann nicht in den folgenden Speicher geschrieben
Zitat:
Außerdem sind die Farben als 4f deklariert aber du ließt nur 3f ein.
Das ist kein Problem, da in der ich in der assign Methode meiner Klassen entsprechend die Daten aus der Datei verwende(Alphawert zuweisen usw.)
Ich hatte mir überlagt das ganze mit den Records zu machen, da ich für den fall das ich noch ein weiteres Dateiformat unterstützen will, nicht noch einmal meine Mesh bzw Material Klasse umschreiben müsste....
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Ich weiß nicht wie du auf den Pointer zugreifst. Ich weiß auch nicht ob Delphi und FPC da evtl unterschiede machen, wenn du FPC benutzen solltest? Ich weiß auch nicht ob dieser Chunk immer existiert. Aber in Delphi ist es so, dass man an Read/Write einen Speicherbereich übergeben muss. Und ein Pointer besteht genau genommen aus zwei Speicherbereichen. Und zwar ein mal dem eigentlichem Datenbereich und ein mal der Variable in der der Pointer gespeichert ist. Folgendes Beispiel.
Code:
TMyRec =record
A:arrayofinteger;
B:integer;
C:Integer;
end;
var
My: TMyRec;
begin
SetLength(My.A,3);
// Das sorgt dafür, dass A, B und C befüllt werden, da der
// Speicherbereich in den Read die Daten packen soll die
// Variable des Pointers für das dynamische Array ist.
Stream.Read(My.A,3*SizeOf(Integer));
// wärend aber durch die Angabe der ersten Stelle explizit der
// Datenbereich benutzt wird
Stream.Read(My.A[0],3*SizeOf(Integer));
end;
Bei Strings oder Pointer mit GetMem ist das Prinzip genau das Gleiche. Die Variable die man benutzt ist grundsätzlich immer ein Pointer. Nur Delphi verschleiert das um die Handhabung zu vereinfachen. Bei der ersten Methode kann es passieren, dass er auch über das eigentliche Record hinwegschreibt und sogar andere Strukturen überschreibt. Und beim nächsten Zugriff auf die anderen Strukturen kracht es. Was evtl auch erklären könnte warum so eine "lächerliche" stelle wie ein SetLength durchknallt. Wenn du dir ausversehen die Daten zerschossen hast.
Registriert: Mi Jan 31, 2007 18:32 Beiträge: 150
Programmiersprache: Pascal
ware schön aber wenn ich diesen chunk einfach ignoriere erhalte ich nicht mehr die Faces meines Meshs kann diesen aber als Punkte wie oben gesagt darstellen und das klappt auch problemlos...auserdem dürfte es dann keinen fehler an dieser stelle geben das es ja egal ist was ein dyn array enthält wenn man die länge ändern will...
wie würde mann dann untypisierte pointer aus einem Stream lesen bzw in einen schreiben(hoffe es ist verständlich was ich damit meine)
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Dazu sollte man zuerst immer die länge der Daten in den Stream schreiben und danach dann den Inhalt des Pointers. Beim Auslesen liest man zuerst die größe aus und kann so den Speicher für den Pointer reservieren:
Code:
var
BlockSize:Integer;
Data:Pointer;
begin
GetMem(Data, BlockSize);
try
// Füll Data mit irgendeinem kram
Stream.Write(BlockSize,SizeOf(Integer));// Die größe des Pointers schreiben
Stream.Write(Data^, BlockSize);// Den Inhalt des Speichers schreiben
finally
FreeMem(Data);
end;
end;
Fürs auslesen dann eben mit Read und so.
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Wenn Vertices ein Pointer ist, ja.
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Mitglieder in diesem Forum: 0 Mitglieder und 9 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.