Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Mo Jul 07, 2025 22:40

Foren-Übersicht » Programmierung » Einsteiger-Fragen
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 16 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Autor Nachricht
 Betreff des Beitrags: EOutOfMemory
BeitragVerfasst: Sa Sep 29, 2007 16:57 
Offline
DGL Member

Registriert: Fr Apr 20, 2007 16:21
Beiträge: 17
So, da bin ich mal wieder :?

Ich habe hier ein Problem, das mich ziemlich stutzig gemacht hat, weil ich das halbe Internet danach ohne Erfolg abgesucht habe, vom Forum ganz zu schweigen. Wahrscheinlich ist die Lösung ganz einfach - ich bin nicht nur in OGL, sondern auch in Delphi und im Programmieren noch recht unerfahren und kenne deshalb vermutlich die ein oder andere nüztliche Methode noch nicht.

Es geht um das Einlesen von Daten. zB 1G Vertices. Diese lese ich aus einer Datei aus - aber wie speicher ich sie ab? Ich habe einen dynamischen Array mit Pointern (also List), doch sobald ich die Länge über ca 300M setze, kommt ein EOutOfMemory - zu wenig Arbeitsspeicher, was sicher nicht der Fall ist. Also hab ich mir mehrere Arrays erschaffen, doch an der Höchstgrenze von 300M ändert sich eigentlich nix... Was tun? Soll ich das Zeugs gleich in einer Art Baum speichern?

Danke im Voraus


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Sep 29, 2007 17:06 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Bei einer solch Großen Menge en Vertices sollte man nicht mehr versuchen diese an einem Stück hochladen zu wollen. Zum einen landet dann ja ein beachtlicher Teil im Arbeitsspeicher des PCs, dessen Bandbreite um ein Vielfaches geringer ist als die zwischen GPU und VRAM (DDR2-800 ~3,2 GB/S, Moderne Graka >40GB/s), und zum anderen macht das auch nicht unbedingt jeder Treiber so mit.

Wenn du also so extrem viele Daten hast dann ist es eigentlich unumgänglich diese dynamisch nachzuladen, also zur Laufzeit zu "streamen". Besonders mit Mehrkern-CPUs geht dies sehr bequem, da man dies über den zweiten Kern erledigen kann ohne dass die komplette Anwendung beim Nachladen stehen bleibt. Dann lädst du also nur was sichtbar ist in den Speicher und lädst neu sichtbare Teile dynamisch nach, während sehr alte (schon lange nicht mehr besichtigte Teile) wieder ausm Speicher geworfen werden. VBOs eigenen sich dazu ja sehr gut, da diese u.a. ein Flag haben dass die VBOs fürs dynamische Verändern optimiert.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Sep 29, 2007 20:17 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Apr 25, 2005 17:51
Beiträge: 464
Zitat:
Es geht um das Einlesen von Daten. zB 1G Vertices. Diese lese ich aus einer Datei aus - aber wie speicher ich sie ab? Ich habe einen dynamischen Array mit Pointern (also List), doch sobald ich die Länge über ca 300M setze, kommt ein EOutOfMemory - zu wenig Arbeitsspeicher,


Lösung siehe Post vor mir^^
Der Grund für deine Fehlermeldung is einfach: du hast zwar mehr als die 300 MB frei. Wenn du aber ein zusammenhängendes Array allokierst, muss der geforderter Speicher adressmäßig am Stück frei sein! Dein Speicher is aber fragmentiert. WEnn du also z.B. 400 MB als Feld haben willst und dein RAM hat einmal 200 und einmal 300 MB frei, dann hast du zwar 500 MB RAM frei, aber halt keinen Block mit 400 MB, ergo kommt die Exception.

_________________
__________
"C++ is the best language for garbage collection principally because it creates less garbage." Bjarne Stroustrup


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Okt 02, 2007 14:22 
Offline
DGL Member

Registriert: Fr Apr 20, 2007 16:21
Beiträge: 17
Okay. Damit kann ich mich abfinden. 1G Vertices werd ich wohl auch nicht brauchen :shock:

Es geht immer noch um meinen .obj -Loader. Ich habe eine 20-mb Datei mit 240k Vertices und 170k Faces, die ich einlese. Irgendwann kommt dann wiede dieser schöne Fehler, ich schaue in den Taskmanager und dort steht bei Project1.exe Speicherauslastung: 40.000K - also 40MB. Da sollte doch dann eigentlich noch kein Fehler auftreten, wenn ich das richtig verstanden hab? Schließlich brauchen einige Programme locker 100MB. Oder liegt es daran, dass ich so lange Arrays hab?

:roll:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Okt 02, 2007 15:20 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Also 20 MB sollten normal überhaupt kein Problem sein. Allerdings weiß ich nicht wie du dein Array erstellst? Evtl wäre da etwas Code ganz nützlich. Wenn nicht sogar unabdingbar.

Bei den Programmen die du gesehen hast tippe ich auch mal darauf, dass die eher kleinere Speicherbereiche alloziiert haben. Und wie Pellaeon schon gesagt hatte genügen teilweise ungünstige Konstellationen die dazu führen können, dass der Speicher etwas zerhackstückelt wird. Und ein Array setzt immer vorraus, dass die Daten an einem Stück im Speicher liegen. Spontan könnte ich mir auch gut vorstellen, dass häufiges SetLength bei einem Array (zum Hinzufügen eines Vertices) recht schnell zu so etwas führen kann. Das ist aber nur ein Tipp ins Blaue.


PS: Je nachdem wie groß es später noch werden kann (Du erwähntest etwas von 300 MB) solltest du dir evtl auch eine ganze andere Struktur ausdenken. Denn dann kommt es sehr stark darauf an was du mit den Daten machen willst und wofür der Loader geschrieben wird? Evtl wäre dann bei sehr großen Datenmengen auch ein Ansatz von Nöten bei dem du lediglich die Datei analysierst und dir gewisse Informationen in deiner Anwenung ablegst. Also nur die Informationen welche Meshes in der Datei stecken und wo sie in der Datei stecken um sie später mehr oder weniger direkt von der Festplatte auf den Grafikspeicher zu laden. Welchen Einsatz dein Code später haben wird ist aber etwas was du dir selbst überlegen musst! Aber 20 MB an Daten sind zwar nicht wenig aber auch nicht wirklich viel.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Okt 02, 2007 16:23 
Offline
DGL Member

Registriert: Di Jun 06, 2006 09:59
Beiträge: 474
Du könntest versuchen FastMM4 einzubinden. Der Delphi-Speichermanager ist(zumindest in alten Delphis) manchmal etwas seltsam. Im notfall kannst du dir gleich nach programmstart mit VirtualAlloc mit Commit flag einen großen zusammenhängengen speicherbereich reservieren, und dann selbst managen.

Und das dynamische array mit pointern, soll das heißen dass du für jedes Arrayelement ein eigenes Objekt allocierst?

_________________
Bild


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Okt 02, 2007 22:06 
Offline
DGL Member

Registriert: Fr Apr 20, 2007 16:21
Beiträge: 17
Zuerst einmal Vielen Dank für die schnellen Antworten. Ich habe noch ein bisschen an meinem Projekt gebastelt, und plötzlich ging das Laden - obwohl ich eigentlich kaum etwas verändert habe... Naja, falls das Problem noch einmal autauchen sollte - ich werds vielleicht mal mit ein bisschen größeren Dateien probieren - meld ich mich wieder :shock:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Okt 02, 2007 22:34 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Will hat geschrieben:
Zuerst einmal Vielen Dank für die schnellen Antworten. Ich habe noch ein bisschen an meinem Projekt gebastelt, und plötzlich ging das Laden


Das dürfte sich dann vielleicht mit einer günstigeren Konstellation im Arbeitsspeicher erklären lassen. Wie Lossy sagte, ich denke auch, dass du mal deinen Code auf häufige Größenänderungen bei Array / Strings prüfen solltest. Z.B. ist eine Schleife, wo bei jedem Durchlauf immer ein Element an ein Array / String angehängt wird der Speicherkiller schlechthin.

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 networkmy 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


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Okt 03, 2007 08:38 
Offline
DGL Member

Registriert: Fr Apr 20, 2007 16:21
Beiträge: 17
Ich habe eigentlich schon versucht, die Anzahl der SetLength-Aufrufe gering zu halten, da sich das ja auch sehr stark auf die Geschwindigkeit auswirkt. Der Array wird immer um 100 Elemente vergrößert.
Gibt es ansonsten irgendwo eine Seite, wo der Speicherbedarf und die Speicherstruktur Delphis übersichtlich dargestellt werden?


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Okt 03, 2007 10:15 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7810
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Siehe http://www.dsdt.info/links/links.php?id=375 (MemCheck)

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Okt 03, 2007 13:38 
Offline
DGL Member

Registriert: Fr Apr 20, 2007 16:21
Beiträge: 17
hm, damit muss ich mich erst einmal genauer auseinanersetzen; danke für den Link.
Ich glaube allerdings nicht, dass ich viele Speicherlöcher habe, denn nach einem kompletten NeuCode hat das Programm eine Speicherauslastung von ca 45.000k (vorher ca 400.000k).
Aber ich habe mich zu früh gefreut - die uses-Zeile um glBitmap.pas ergänzt, und dann war auch schon wieder Essig. Deshalb poste ich hier jetzt mal den Code...
Der Fehler trat bei einer 20mb-Datei mit 240k Vertices+Normals und 170k Faces auf - wie gehabt eben.
Also im Voraus schon einmal entschuldigung für die Länge und den Programmierstil :shock: Doch die entscheidenden Stellen für die Struktur der Daten sind eigentlich recht übersichtlich (hoffe ich), und lieber zu viel Code als zu wenig ^^.
[Edit] Diese grässliche Formatierung kommt von den Pascal-Tags... :shock: [/Edit]

Die erste Unit uMeshGlobals definiert nur so ein paar Typen, die ich brauche, sowie die Klasse TMesh. Ein TMesh enthält nur die Information, unter welchem Index die Vectoren etc für jedes Face vorhanden sind, die Daten selbst befinden sich in TMeshManager (uMeshManager).

Um zu viel Array-Resizing zu vermeiden, benutze ich die Prozeduren IncRange und FitRange, die die Arrays um jeweils 100 Elemente vergrößern bzw anpassen.
Naja, viel Glück, vielleicht wird ja jemand fündig...

Code:
  1. unit uMeshGlobals;
  2.  
  3. interface
  4.  
  5. uses
  6.  dglOpengl,
  7.  StrUtils,SysUtils;
  8.  
  9. type
  10.  TDrawMode =    (dmTexture,dmWireframe,dmPoints);
  11.  
  12.  PVector3f =    ^TGLVector3f;
  13.  TVector3f =    TGLVector3f;
  14.  
  15.  PVector2f =    ^TVector2f;
  16.  TVector2f =    array[0..1] of Single;
  17.  
  18.  PFullVertex =  ^TFullVertex;
  19.  TFullVertex =  record
  20.   Vec,Nor:       TVector3f;
  21.   UV:            TVector2f;
  22.  end;
  23.  
  24.  PFaceIndex =    ^TFaceIndex;
  25.  TFaceIndex =    packed record
  26.   cVertices:      Byte;
  27.   HasMaterial:    Boolean;
  28.   HasNormals:     Boolean;
  29.   HasTexCoord:    Boolean;
  30.   MaterialName:   string;
  31.   iMaterial:      integer;
  32.   irgVertices:    array of packed record
  33.    iVector:        integer;
  34.    iNormal:        integer;
  35.    iTexCoord:     integer;
  36.   end;
  37.  end;
  38.  
  39.  PMaterial =      ^TMaterial;
  40.  TMaterial =      packed record
  41.   Name:            string;
  42.     Ambient:         TVector3f;
  43.     Diffuse:         TVector3f;
  44.     Specular:        TVector3f;
  45.     Shininess:       Single;
  46.     Alpha:           Single;
  47.   TextureID:       integer;
  48.  end;
  49.  
  50.  T3DObject =      class(TObject)
  51.   Name:            string;
  52.   LocalMatrix:     TMatrix4f;
  53.  end;
  54.  
  55.  PMesh =          ^TMesh;
  56.  TMesh =          class(T3DObject)
  57.   FDrawMode:       TDrawMode;
  58.   cFaces:          integer;
  59.   rgFaces:         array of TFaceIndex;
  60.   procedure        IncFacesRange;
  61.   procedure        FitFacesRange;
  62.   constructor      Create;
  63.   destructor       Destroy;
  64.   procedure        Init;
  65.   procedure        NewFace;
  66.   procedure        AddFullVertex(pVector, pNormal, pTexCoord: integer);
  67.  end;
  68.  
  69. implementation
  70.  
  71. constructor TMesh.Create;
  72. begin
  73.  Init;
  74. end;
  75.  
  76. destructor TMesh.Destroy;
  77. begin
  78.  //
  79. end;
  80.  
  81. procedure TMesh.Init;
  82. begin
  83.  SetLength(rgFaces,0);
  84.  cFaces:=0;
  85.  FDrawMode:=dmTexture;
  86. end;
  87.  
  88. procedure TMesh.IncFacesRange;
  89. var tmpint: integer;
  90. begin
  91.  tmpint:=Length(rgFaces)-cFaces;
  92.  cFaces:=cFaces+1;
  93.  if tmpint<=0 then
  94.   SetLength(rgFaces, Length(rgFaces)+100);
  95. end;
  96.  
  97. procedure TMesh.FitFacesRange;
  98. begin
  99.  SetLength(rgFaces,cFaces);
  100. end;
  101.  
  102. procedure TMesh.NewFace;
  103. begin
  104.  IncFacesRange;
  105.  rgFaces[cFaces-1].cVertices:=0;
  106. end;
  107.  
  108. procedure TMesh.AddFullVertex(pVector, pNormal, pTexCoord: integer);
  109. begin
  110.  with rgFaces[cFaces-1] do
  111.   begin
  112.    SetLength(irgVertices,cVertices+1);
  113.    cVertices:=cVertices+1;
  114.    irgVertices[cVertices-1].iVector:=pVector;
  115.    irgVertices[cVertices-1].iNormal:=pNormal;
  116.    irgVertices[cVertices-1].iTexCoord:=pTexCoord;
  117.   end;
  118. end;
  119.  
  120. end.






Code:
  1. unit uMeshManager;
  2.  
  3. interface
  4.  
  5. uses
  6.  uMeshGlobals,uTextureManager,dglOpengl,
  7.  Windows,StrUtils,SysUtils,Dialogs;
  8.  
  9. type
  10.  TMultiString = array of string;
  11.  
  12.  TLoadLog = record
  13.   Name: string;
  14.   VertexCount, FaceCount, MaterialCount: integer;
  15.  end;
  16.  
  17.  TMeshManagerItem = (mmiMaterial,mmiVertex,mmiNormal,mmiTexCoord);
  18.  
  19.  TMeshManager = class(TObject)
  20.  private
  21.   TextureManager: TTextureManager;
  22.  
  23.   FDead:       Boolean;
  24.   cMeshes:     integer;
  25.   cMaterials:  integer;                                                        
  26.   cVertices:   integer;
  27.   cNormals:    integer;                                                        
  28.   cTexCoord:   integer;
  29.   rgMeshes:    array of TMesh;
  30.   rgMaterials: array of TMaterial;
  31.   rgVertices:  array of TVector3f;
  32.   rgNormals:   array of TVector3f;
  33.   rgTexCoord:  array of TVector3f;
  34.  public
  35.   constructor  Create;
  36.   destructor   Destroy;
  37.   procedure    Init;
  38.   procedure    IncRange(pToChange: TMeshManagerItem);
  39.   procedure    FitRange(pToChange: TMeshManagerItem);
  40.   function     LoadMeshFromWavefront(pFileName: string): Boolean;
  41.   procedure    LoadMeshFromStream;
  42.   procedure    DrawMesh(pMeshIndex: integer);
  43.   function     CompileMesh(pMeshIndex: integer): integer;
  44.   //function     LoadMaterialFromWavefront(pFileName: string): Boolean;
  45.   //procedure    LoadMaterialFromStream;
  46.   procedure    SaveDataAnalysis(pFileName: string);
  47.  end;
  48.  
  49. var istart,iend,ifreq: Int64;
  50.  
  51. implementation
  52.  
  53. {+----------------------------------------------------------------------------+}
  54. {|                                                                            |}
  55. {| TMeshManager                                                               |}
  56. {|                                                                            |}
  57. {+----------------------------------------------------------------------------+}
  58.  
  59. constructor TMeshManager.Create;
  60. begin
  61.  Init;
  62. end;
  63.  
  64. destructor TMeshManager.Destroy;
  65. begin
  66.  //
  67. end;
  68.  
  69. procedure TMeshManager.Init;
  70. var i: integer;
  71. begin
  72.  FDead:=false;
  73.  for i:=0 to cMeshes-1 do
  74.   rgMeshes[i].Destroy;
  75.  cMeshes:=0;
  76.  SetLength(rgMeshes,0);
  77.  cMaterials:=0;
  78.  SetLength(rgMaterials,0);
  79.  cVertices:=0;
  80.  SetLength(rgVertices,0);
  81.  cNormals:=0;
  82.  SetLength(rgNormals,0);
  83.  cTexCoord:=0;
  84.  SetLength(rgTexCoord,0);
  85. end;
  86.  
  87. procedure TMeshManager.IncRange(pToChange: TMeshManagerItem);
  88. var tmpint: integer;
  89. begin
  90.  case pToChange of
  91.   mmiMaterial:
  92.    begin
  93.     tmpint:=Length(rgMaterials)-cMaterials;
  94.     cMaterials:=cMaterials+1;
  95.     if tmpint<=0 then
  96.      SetLength(rgMaterials, Length(rgMaterials)+1000);
  97.    end;
  98.   mmiVertex:
  99.    begin
  100.     tmpint:=Length(rgVertices)-cVertices;
  101.     cVertices:=cVertices+1;
  102.     if tmpint<=0 then
  103.      SetLength(rgVertices, Length(rgVertices)+1000);
  104.    end;
  105.   mmiNormal:
  106.    begin
  107.     tmpint:=Length(rgNormals)-cNormals;
  108.     cNormals:=cNormals+1;
  109.     if tmpint<=0 then
  110.      SetLength(rgNormals, Length(rgNormals)+1000);
  111.    end;
  112.   mmiTexCoord:
  113.    begin
  114.     tmpint:=Length(rgTexCoord)-cTexCoord;
  115.     cTexCoord:=cTexCoord+1;
  116.     if tmpint<=0 then
  117.      SetLength(rgTexCoord, Length(rgTexCoord)+1000);
  118.    end;
  119.  end;
  120. end;
  121.  
  122. procedure TMeshManager.FitRange(pToChange: TMeshManagerItem);
  123. begin
  124.  case pToChange of
  125.   mmiMaterial: SetLength(rgMaterials,cMaterials);
  126.   mmiVertex:   SetLength(rgVertices,cVertices);
  127.   mmiNormal:   SetLength(rgNormals,cNormals);
  128.   mmiTexCoord: SetLength(rgTexCoord,cTexCoord);
  129.  end;
  130. end;
  131.  
  132. //------------------------------------------------------------------------------
  133. function TMeshManager.LoadMeshFromWavefront(pFileName: string): Boolean;
  134. var Mult,Mult2: TMultistring;
  135. var L,S,MaterialFileName: string;
  136. var F: TextFile;
  137. var tmpMat: string;
  138. var i,j: integer;
  139. var HasTexCoord,HasNormals: Boolean;
  140.  
  141.  function PosEx(const substr: AnsiString; const s: AnsiString; const start: Integer ): Integer ;
  142.  type StrRec = record allocSiz: Longint; refCnt: Longint; length: Longint; end;
  143.  const  skew = sizeof(StrRec);
  144.  asm
  145.                 TEST    EAX,EAX
  146.                 JE      @@noWork
  147.                 TEST    EDX,EDX
  148.                 JE      @@stringEmpty
  149.                 TEST    ECX,ECX
  150.                 JE      @@stringEmpty
  151.                 PUSH    EBX
  152.         PUSH    ESI
  153.                 PUSH    EDI
  154.                 MOV     ESI,EAX
  155.                 MOV     EDI,EDX
  156.                 MOV     EBX,ECX
  157.                 MOV     ECX,[EDI-skew].StrRec.length
  158.                 PUSH    EDI
  159.                 CMP     EBX,ECX
  160.                 JG      @@fail
  161.                 MOV     EDX,[ESI-skew].StrRec.length
  162.                 DEC     EDX
  163.                 JS      @@fail                          
  164.                 MOV     AL,[ESI]
  165.                 INC     ESI                            
  166.                 SUB     ECX,EDX
  167.         JLE     @@fail
  168.                 DEC     EBX
  169.                 SUB     ECX,EBX  
  170.                 JLE     @@fail    
  171.                 ADD     EDI,EBX  
  172.     @@loop:
  173.                 REPNE   SCASB
  174.                 JNE     @@fail
  175.                 MOV     EBX,ECX                        
  176.                 PUSH    ESI
  177.                 PUSH    EDI                            
  178.                 MOV     ECX,EDX
  179.                 REPE    CMPSB
  180.                 POP     EDI                            
  181.                 POP     ESI                            
  182.                 JE      @@found
  183.                 MOV     ECX,EBX                        
  184.                 JMP     @@loop
  185.     @@fail:
  186.                 POP     EDX
  187.                 XOR     EAX,EAX
  188.                 JMP     @@exit
  189.     @@stringEmpty:
  190.                 XOR     EAX,EAX
  191.                 JMP     @@noWork
  192.     @@found:
  193.                 POP     EDX                            
  194.                 MOV     EAX,EDI
  195.                 SUB     EAX,EDX                        
  196.     @@exit:
  197.                 POP     EDI
  198.                 POP     ESI
  199.                 POP     EBX
  200.     @@noWork:
  201.  end;
  202.  
  203.  //zerteilt einen String <Input> ab Position <Offset>  mit dem Trennzeichen <Chr>
  204.  //und gibt die ersten <Count> Teilstrings in einem Array aus
  205.  function Extract(Input: String; Count: Byte; Offset: Cardinal=1; Chr: Char=' '): TMultiString;
  206.  var M1,M2,k: integer;
  207.  begin
  208.     SetLength(result,Count);
  209.     SetLength(Input,Length(Input)+1);
  210.     Input[Length(Input)]:=Chr;
  211.     if Offset>1 then
  212.      M2:=PosEx(Chr,Input,1)
  213.     else
  214.      M2:=0;
  215.     for k:=0 to Count-1 do
  216.      begin
  217.         repeat
  218.          begin
  219.             M1:=M2+1;
  220.             M2:=PosEx(Chr,Input,M1);
  221.          end;
  222.         until (M1<>M2);
  223.         result[k]:=Copy(Input,M1,M2-M1);
  224.         if M1=Length(Input)+1 then
  225.          begin
  226.             SetLength(result,k);
  227.             exit;
  228.          end;
  229.      end;
  230.  end;
  231.  
  232.  procedure ReadMaterialFileName;
  233.  begin
  234.     Mult:=Extract(S,1,2,' ');
  235.   MaterialFileName:=Mult[0]
  236.  end;
  237.  
  238.  procedure ReadObjectName;
  239.  begin
  240.   Mult:=Extract(S,1,2,' ');
  241.  end;
  242.  
  243.  procedure ReadVertices;
  244.  begin
  245.     Mult:=Extract(AnsiReplaceStr(S,'.',','),3,2);
  246.   IncRange(mmiVertex);
  247.   rgVertices[cVertices-1,0]:=strtofloat(Mult[0]);
  248.   rgVertices[cVertices-1,1]:=strtofloat(Mult[1]);
  249.   rgVertices[cVertices-1,2]:=strtofloat(Mult[2]);
  250.  end;
  251.  
  252.  procedure ReadTexCoord;
  253.  begin
  254.     Mult:=Extract(AnsiReplaceStr(S,'.',','),3,2);
  255.   IncRange(mmiTexCoord);
  256.   rgTexCoord[cTexCoord-1,0]:=strtofloat(Mult[0]);
  257.   rgTexCoord[cTexCoord-1,1]:=strtofloat(Mult[1]);
  258.   HasTexCoord:=true;
  259.  end;
  260.  
  261.  procedure ReadNormals;
  262.  begin
  263.     Mult:=Extract(AnsiReplaceStr(S,'.',','),3,2);
  264.   IncRange(mmiNormal);
  265.   rgNormals[cNormals-1,0]:=strtofloat(Mult[0]);
  266.   rgNormals[cNormals-1,1]:=strtofloat(Mult[1]);
  267.   rgNormals[cNormals-1,2]:=strtofloat(Mult[2]);
  268.   HasNormals:=true;
  269.  end;
  270.  
  271.  procedure ReadMaterialName;
  272.  begin
  273.     Mult:=Extract(S,1,2);
  274.   IncRange(mmiMaterial);
  275.   rgMaterials[cMaterials-1].Name:=Mult[0];
  276.  end;
  277.  
  278.  procedure ReadAmbient;
  279.  begin
  280.   Mult:=Extract(AnsiReplaceStr(S,'.',','),3,2);
  281.   rgMaterials[cMaterials-1].Ambient[0]:=strtofloat(Mult[0]);
  282.   rgMaterials[cMaterials-1].Ambient[1]:=strtofloat(Mult[1]);
  283.   rgMaterials[cMaterials-1].Ambient[2]:=strtofloat(Mult[2]);
  284.  end;
  285.  
  286.  procedure ReadDiffuse;
  287.  begin
  288.   Mult:=Extract(AnsiReplaceStr(S,'.',','),3,2);
  289.   rgMaterials[cMaterials-1].Diffuse[0]:=strtofloat(Mult[0]);
  290.   rgMaterials[cMaterials-1].Diffuse[1]:=strtofloat(Mult[1]);
  291.   rgMaterials[cMaterials-1].Diffuse[2]:=strtofloat(Mult[2]);
  292.  end;
  293.  
  294.  procedure ReadSpecular;
  295.  begin
  296.   Mult:=Extract(AnsiReplaceStr(S,'.',','),3,2);
  297.   rgMaterials[cMaterials-1].Specular[0]:=strtofloat(Mult[0]);
  298.   rgMaterials[cMaterials-1].Specular[1]:=strtofloat(Mult[1]);
  299.   rgMaterials[cMaterials-1].Specular[2]:=strtofloat(Mult[2]);
  300.  end;
  301.  
  302.  procedure ReadShininess;
  303.  begin
  304.     Mult:=Extract(AnsiReplaceStr(S,'.',','),1,2);
  305.   rgMaterials[cMaterials-1].Shininess:=strtofloat(Mult[0]);
  306.  end;
  307.  
  308.  procedure ReadAlpha;
  309.  begin
  310.     Mult:=Extract(AnsiReplaceStr(S,'.',','),1,2);
  311.   rgMaterials[cMaterials-1].Alpha:=strtofloat(Mult[0]);
  312.  end;
  313.  
  314.  procedure ReadTexture;
  315.  begin
  316.   //
  317.  end;
  318.  
  319.  procedure ReadFace;
  320.  var k: integer;
  321.  var tmpVector,tmpNormal,tmpTexCoord: integer;
  322.  begin
  323.     rgMeshes[cMeshes].NewFace;
  324.   rgMeshes[cMeshes].rgFaces[rgMeshes[cMeshes].cFaces-1].MaterialName:=tmpMat;
  325.     Mult:=Extract(S,100,2);
  326.     for k:=0 to Length(Mult)-1 do
  327.      begin
  328.     tmpVector:=-1;
  329.     tmpNormal:=-1;
  330.     tmpTexCoord:=-1;
  331.         Mult2:=Extract(Mult[k],3,1,'/');
  332.     tmpVector:=strtoint(Mult2[0]);                                              //Achtung: in obj geht auch das hier: f -1 2 -4 5 !!!!
  333.         if HasTexCoord and not HasNormals then
  334.          begin
  335.             tmpTexCoord:=strtoint(Mult2[1]);
  336.          end;
  337.         if HasNormals and not HasTexCoord then
  338.          begin
  339.             tmpNormal:=strtoint(Mult2[1]);
  340.          end;
  341.         if HasNormals and HasTexCoord then
  342.          begin
  343.             tmpTexCoord:=strtoint(Mult2[1]);
  344.             tmpNormal:=strtoint(Mult2[2]);
  345.          end;
  346.      rgMeshes[cMeshes].AddFullVertex(tmpVector,tmpNormal,tmpTexCoord);
  347.      end;
  348.  
  349.  end;
  350.  
  351. //------------------------------------------------------------------------------
  352. begin
  353.  QueryPerformanceFrequency(ifreq);
  354.  QueryPerformanceCounter(istart);
  355.  
  356.  result:=false;
  357.  HasTexCoord:=false;
  358.  HasNormals:=false;
  359.  
  360.  SetLength(rgMeshes,cMeshes+1);
  361.  rgMeshes[cMeshes]:=TMesh.Create;
  362.  
  363.  if not FileExists(pFileName) then
  364.     exit;
  365.   //event
  366.  AssignFile(F, pFileName);
  367.  Reset(F);
  368.  repeat
  369.     begin
  370.      ReadLn(F,S);
  371.      SetLength(S,Length(S)+1);
  372.      S[Length(S)]:=' ';
  373.      L:=Uppercase(Copy(S,1,2));
  374.      case L[1] of
  375.         'V': case L[2] of
  376.                      ' ': ReadVertices;
  377.                      'T': ReadTexCoord;
  378.                      'N': ReadNormals;
  379.                      //event
  380.                      end;      
  381.         'M': ReadMaterialFileName;
  382.         'O': ReadObjectName;
  383.         'U': ReadMaterialFileName;
  384.         'F': ReadFace;
  385.         'S': ;
  386.         'G': ;
  387.         '#': ;
  388.         ' ': ;
  389.         //event
  390.         end;
  391.     end;
  392.  until EOF(F);
  393.  CloseFile(F);
  394.  
  395.  if MaterialFileName<>'null' then
  396.   begin
  397.    MaterialFileName:=Copy(pFileName,1,Length(pFileName)-4)+'.mtl';
  398.    if not FileExists(MaterialFileName) then
  399.       exit;
  400.    //event
  401.    AssignFile(F,MaterialFileName);
  402.    Reset(F);
  403.    repeat
  404.       begin
  405.        ReadLn(F,S);
  406.        SetLength(S,Length(S)+1);
  407.        S[Length(S)]:=' ';
  408.        L:=Uppercase(Copy(S,1,2));
  409.        case L[1] of
  410.           'N': case L[2] of
  411.                       'E': ReadMaterialName;
  412.                       'I': ReadShininess;
  413.                       'S': ;
  414.                       end;
  415.           'K': case L[2] of
  416.                       'A': ReadAmbient;
  417.                       'D': ReadDiffuse;
  418.                       'S': ReadSpecular;
  419.                     end;
  420.           'D': ReadAlpha;
  421.           'I': ;
  422.           '#': ;
  423.           ' ': ;
  424.           end;
  425.       end;
  426.    until EOF(F);
  427.    CloseFile(F);
  428.  
  429.   for i:=0 to rgMeshes[cMeshes].cFaces-1 do
  430.    for j:=0 to cMaterials-1 do
  431.     if rgMeshes[cMeshes].rgFaces[i].MaterialName=rgMaterials[j].Name then
  432.      rgMeshes[cMeshes].rgFaces[i].iMaterial:=j;
  433.   end;
  434.  
  435.  FitRange(mmiMaterial);
  436.  FitRange(mmiVertex);
  437.  FitRange(mmiNormal);
  438.  FitRange(mmiTexCoord);
  439.  rgMeshes[cMeshes].FitFacesRange;
  440.  
  441.  //Normalen berechnen
  442.  
  443.  //Vertices, Faces etc zählen
  444.  
  445.  cMeshes:=cMeshes+1;
  446.  
  447.  QueryPerformanceCounter(iend);
  448.  ShowMessage(floattostr((iend-istart)/ifreq));
  449.  
  450.  result:=true;
  451. end;


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Okt 03, 2007 14:06 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jul 29, 2003 00:11
Beiträge: 436
Ohne den Code angesehen zu haben: Warum ein Array? Musst du viele indizierte Zugriffe machen oder traversierst du das am Ende komplett? Wenn letzteres, dann ist wohl eine verkettete Liste 'ne bessere Idee, damit rennst du jedenfalls nicht in die Speicherfragmentierungsproblematik.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Okt 04, 2007 09:49 
Offline
DGL Member

Registriert: Fr Apr 20, 2007 16:21
Beiträge: 17
Das Wavefront-Format sieht ja so aus:

v -1 -1 0
v -1 1 0
v 1 1 0
v 1 -1 0
f 1 2 3 4

Ich weiß jetzt nicht wie das bei anderen 3D-Formaten ist, aber hier bieten sich Arrays natürlich an, da f nur die Indizes der Vertices angibt... Ich wollte dann eigentlich noch mein eigenes Format schreiben, wo das dann vielleicht anders ist, aber zuerst einmal muss ich die Daten einlesen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Okt 04, 2007 11:41 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Erst mal etwas ganz wichtiges. In Klassen grundsätzlich IMMER inherited benutzen. Bei einer Klasse die von TObject abgelitten ist das zwar nicht soo tragisch ändern aber nichts, dass es eigentlich trotzdem immer benutzen werden sollte.

Da du ja doch schon sehr viel mit wirklich größeren Daten zu tun hast solltest du dir überlegen ob du das nicht vielleicht etwas anders aufziehen solltest. Du darfst auch nicht vergessen. Die Strings sind auch nur dynamische Arrays. Und ein SetLength +1 bei einem String erfordert höchstwahrscheinlich auch schon, dass dieser verschoben werden muss.

Eine Idee von mir wäre mehr oder weniger ganz auf die Arrays zu verzichten und statt dessen kleine Blöcke zu benutzen. Denn wie gesagt. In einem Array müssen die Daten immer am Stück liegen. Und du hast gleich mehrere davon. Und ich denke genau da wird dein Hauptproblem liegen. Jetzt aber meine Idee. Ich bitte zu bedenken, dass ich normal keine Modelloader schreibe weswegen das Ganze eher als grobes Schema zu betrachten ist. Und dabei auch nur das Ablegen der Vertexdaten. Wenn ich deinen Code richtig verstanden habe, dann reagierst du auch nur auf die ersten Texturkoordinaten. Was die Sache vereinfacht also betrachte ich ein Vertex folgendermaßen.
Code:
  1. PVertex = ^TVertex;
  2. TVertex = packed record
  3.   Material: TMaterial;
  4.   Vertice: TVector3f;
  5.   Normal: TVector3f;
  6.   TexCoord: TVector2f;
  7. end;

Für die Speicherverwaltung würde ich eine extra Klasse schreiben. Diese würde dann Methoden bieten AddVertex, GetVertex. Intern würde bei AddVertex dann folgendes ablaufen. Er würde überprüfen ob er noch genug Platz in seinen Buffern hätte. Da du beim Laden aber eher keine Vertices löscht brauchst du auch auch nur am Ende zu schauen ob noch platz ist. Falls nicht genügend Platz vorhanden ist dann würde er einen Speicherblock mit GetMem alloziieren. Dieser hätte die Größe von 500 * SizeOf(TVertex) (500 sind womöglich zu viel). Diesen Speicherblöck würde er in eine TList hängen. Als Rückgabewert von AddVertex würde ich dann den Pointer auf ein freies Vertex innerhalb des Speichers zurückgeben. Also ein PVertex welches du dann ganz normal füllen kannst. Die Daten würden dann direkt in den Speicher wandern.

Dadurch, dass du alles intern handhabst kommen nur neue Blöcke hinzu aber es muss kein Block umkopiert werden etc. Und da alle Blöcke gleich groß sein werden kannst du recht einfach erreichnen wo sich das 2042te Vertex befindet und dieses zurückgeben. Von außen würde es sich auch noch fast wie ein Array anfühlen. Nur, dass es intern halt auf 20x dieser kleineren Blöcke verteilt wird.

Solltest du die Daten in einen anderen Speicherbereich kopieren müssen (VBO) musst du das lediglich bei den Methoden berücksichtigen. Komplizierter wird es allerdings wenn die Vertices eine unterschiedliche Anzahl an Texturkoordinaten haben können. Aber da weiß ich nicht mal ob das vom Format her überhaupt möglich ist.

Ist wie gesagt eine Idee. Lass dir mal durch den Kopf gehen ob es für deine Aufgaben ausreicht. Allerdings würde ich es schon so machen, dass man die Daten in kleineren, sich nicht in der Größe verändernden, Blöcken ablegt. Dann bekommt auch der Speichermanager keinen Schock mehr.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Okt 04, 2007 15:18 
Offline
DGL Member

Registriert: Fr Apr 20, 2007 16:21
Beiträge: 17
Vielen Dank für die ausführliche Antwort.
Wie bereits erwähnt, bin ich in Delphi oder Programmierung allgemein noch nicht so erfahren, so dass ich von selbst auf eine solche Lösung noch gar nicht gekommen wäre. Wie dem auch sein, ich werde mir gleich mal so eine Klasse für die Speicherverwaltung schreiben und das ganze ausprobieren. Klingt vielversprechend..
:D


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 16 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Foren-Übersicht » Programmierung » Einsteiger-Fragen


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 5 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.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.015s | 15 Queries | GZIP : On ]