~ubuntu-branches/ubuntu/utopic/castle-game-engine/utopic

« back to all changes in this revision

Viewing changes to src/x3d/x3dloadinternalgeo.pas

  • Committer: Package Import Robot
  • Author(s): Abou Al Montacir
  • Date: 2013-04-27 18:06:40 UTC
  • Revision ID: package-import@ubuntu.com-20130427180640-eink4nmwzuivez1c
Tags: upstream-4.0.1
ImportĀ upstreamĀ versionĀ 4.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
{
 
2
  Copyright 2002-2013 Michalis Kamburelis.
 
3
 
 
4
  This file is part of "Castle Game Engine".
 
5
 
 
6
  "Castle Game Engine" is free software; see the file COPYING.txt,
 
7
  included in this distribution, for details about the copyright.
 
8
 
 
9
  "Castle Game Engine" is distributed in the hope that it will be useful,
 
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
12
 
 
13
  ----------------------------------------------------------------------------
 
14
}
 
15
 
 
16
{ Load 3D Videoscape GEO models.
 
17
  See [http://local.wasp.uwa.edu.au/~pbourke/dataformats/geo/].
 
18
  We handle basic geometry, we can open files exported by Blender exporter. }
 
19
unit X3DLoadInternalGEO;
 
20
 
 
21
interface
 
22
 
 
23
uses X3DNodes;
 
24
 
 
25
function LoadGEO(const filename: string): TX3DRootNode;
 
26
 
 
27
implementation
 
28
 
 
29
uses CastleVectors, CastleUtils, Classes, SysUtils,
 
30
  CastleFilesUtils, CastleStringUtils, X3DLoadInternalUtils;
 
31
 
 
32
{ TObject3DGEO ---------------------------------------------------------------- }
 
33
 
 
34
type
 
35
  { Reader of GEO files.
 
36
    Note that contents of Verts and Faces are read-only for user of this unit. }
 
37
  TObject3DGEO = class
 
38
  public
 
39
    Verts: TVector3SingleList;
 
40
    Faces: TVector3CardinalList;
 
41
    constructor Create(const fname: string);
 
42
    destructor Destroy; override;
 
43
  end;
 
44
 
 
45
constructor TObject3DGEO.Create(const fname: string);
 
46
type
 
47
  TGEOFormatFlavor = (gfOld, gfMeshColorFaces, gfMeshColorVerts);
 
48
var
 
49
  Flavor: TGEOFormatFlavor;
 
50
 
 
51
  function ReadVertexIndex(var F: TextFile): Cardinal;
 
52
  begin
 
53
    Read(F, Result);
 
54
    { In older format, vertex index is 1-based. }
 
55
    if Flavor = gfOld then Dec(Result);
 
56
  end;
 
57
 
 
58
  { Read exactly one line of GEO file, reading new face information.
 
59
    Updates Faces. }
 
60
  procedure ReadGEOFace(var F: TextFile);
 
61
  var
 
62
    J, ThisPolyCount: Integer;
 
63
    FirstVert, LastVert: Cardinal;
 
64
    CurrentFace: PVector3Cardinal;
 
65
  begin
 
66
    Read(F, ThisPolyCount);
 
67
 
 
68
    CurrentFace := Faces.Add;
 
69
 
 
70
    { odczytaj "na pewniaka" pierwszy trojkat }
 
71
    for j := 0 to 2 do
 
72
      CurrentFace^[j] := ReadVertexIndex(F);
 
73
 
 
74
    FirstVert := CurrentFace^[0];
 
75
    LastVert := CurrentFace^[2];
 
76
 
 
77
    { dla kazdego nastepnego vertexa polygonu tworz nowy trojkat jako
 
78
      sklejenie FirstVert, LastVert i nowego vertexa. Pilnuj kolejnosci
 
79
      aby wszystkie trojkaty z tego polygonu byly tak zorientowane jak ten
 
80
      polygon.}
 
81
    for j := 3 to ThisPolyCount - 1 do
 
82
    begin
 
83
      CurrentFace := Faces.Add;
 
84
 
 
85
      CurrentFace^[0] := FirstVert;
 
86
      CurrentFace^[1] := LastVert;
 
87
      CurrentFace^[2] := ReadVertexIndex(F);
 
88
 
 
89
      LastVert := CurrentFace^[2];
 
90
    end;
 
91
    Readln(f);
 
92
  end;
 
93
 
 
94
var
 
95
  f: TextFile;
 
96
  i: Integer;
 
97
  Line: string;
 
98
  VertsCount, PolysCount, VertsInPolysCount: Integer;
 
99
begin
 
100
 inherited Create;
 
101
 Verts := TVector3SingleList.Create;
 
102
 Faces := TVector3CardinalList.Create;
 
103
 
 
104
 SafeReset(f, fname, true);
 
105
 try
 
106
  { Read first line: magic number (or not existent in older GEO format) }
 
107
  Readln(F, Line);
 
108
  Line := Trim(Line);
 
109
  if SameText(Line, '3DG1') then
 
110
    Flavor := gfMeshColorFaces else
 
111
  if SameText(Line, 'GOUR') then
 
112
    Flavor := gfMeshColorVerts else
 
113
    Flavor := gfOld;
 
114
 
 
115
  if Flavor = gfOld then
 
116
  begin
 
117
    { Use current value of Line, for older format the first line contains
 
118
      these counts. }
 
119
    DeFormat(Line, '%d %d %d', [@VertsCount, @PolysCount, @VertsInPolysCount]);
 
120
 
 
121
    { Ile mamy Faces trojkatnych ? Mamy liczbe
 
122
      wielokatow = PolysCount. Mamy sumaryczna liczbe wierzcholkow
 
123
      w nich. Na kazdy polygon przypadaja co najmniej 3 wierzcholki
 
124
      i one daja jeden trojkat. Kazdy nadmiarowy wierzcholek,
 
125
      bez wzgledu na to w ktorym polygonie sie znajdzie, spowoduje
 
126
      utworzenie nowego trojkata. Stad
 
127
        FFacesCount := PolysCount + (VertsInPolysCount - PolysCount * 3);
 
128
      czyli
 
129
        Faces.SetLength(VertsInPolysCount - PolysCount * 2);
 
130
 
 
131
      To cooperate with other Flavor, we do not set Faces.Count directly,
 
132
      instead we set only Capacity.
 
133
    }
 
134
    Faces.Capacity := VertsInPolysCount - PolysCount * 2;
 
135
  end else
 
136
  begin
 
137
    { In newer formats, 2nd line contains just VertsCount. }
 
138
    Readln(F, VertsCount);
 
139
    PolysCount := -1;
 
140
  end;
 
141
 
 
142
  Verts.Count := VertsCount;
 
143
  for i := 0 to Verts.Count-1 do
 
144
    Readln(f, Verts.L[i][0], Verts.L[i][1], Verts.L[i][2]);
 
145
 
 
146
  if PolysCount <> -1 then
 
147
  begin
 
148
    for i := 0 to PolysCount - 1 do
 
149
      ReadGEOFace(F);
 
150
  end else
 
151
  begin
 
152
    { PolysCount not known. So we just read the file as fas as we can. }
 
153
    while not SeekEof(F) do
 
154
      ReadGEOFace(F);
 
155
  end;
 
156
 finally CloseFile(f) end;
 
157
end;
 
158
 
 
159
destructor TObject3DGEO.Destroy;
 
160
begin
 
161
 Verts.Free;
 
162
 Faces.Free;
 
163
 inherited;
 
164
end;
 
165
 
 
166
{ LoadGEO -------------------------------------------------------------------- }
 
167
 
 
168
function LoadGEO(const filename: string): TX3DRootNode;
 
169
var
 
170
  geo: TObject3DGEO;
 
171
  verts: TCoordinateNode;
 
172
  faces: TIndexedFaceSetNode;
 
173
  Shape: TShapeNode;
 
174
  i: integer;
 
175
  BaseUrl: string;
 
176
begin
 
177
  BaseUrl := ExtractFilePath(ExpandFilename(filename));
 
178
  geo := TObject3DGEO.Create(filename);
 
179
  try
 
180
    result := TX3DRootNode.Create('', BaseUrl);
 
181
    try
 
182
      Result.HasForceVersion := true;
 
183
      Result.ForceVersion := X3DVersion;
 
184
 
 
185
      Shape := TShapeNode.Create('', BaseUrl);
 
186
      result.FdChildren.Add(Shape);
 
187
      Shape.Material := TMaterialNode.Create('', BaseUrl);
 
188
 
 
189
      faces := TIndexedFaceSetNode.Create('', BaseUrl);
 
190
      Shape.FdGeometry.Value := faces;
 
191
      faces.FdCreaseAngle.Value := NiceCreaseAngle;
 
192
      faces.FdSolid.Value := false;
 
193
      faces.FdCoordIndex.Count := geo.Faces.Count * 4;
 
194
      for i := 0 to geo.Faces.Count-1 do
 
195
      begin
 
196
        faces.FdCoordIndex.Items.L[i * 4    ] := geo.Faces.L[i][0];
 
197
        faces.FdCoordIndex.Items.L[i * 4 + 1] := geo.Faces.L[i][1];
 
198
        faces.FdCoordIndex.Items.L[i * 4 + 2] := geo.Faces.L[i][2];
 
199
        faces.FdCoordIndex.Items.L[i * 4 + 3] := -1;
 
200
      end;
 
201
 
 
202
      verts := TCoordinateNode.Create('', BaseUrl);
 
203
      faces.FdCoord.Value := verts;
 
204
      verts.FdPoint.Items.Assign(geo.Verts);
 
205
    except result.Free; raise end;
 
206
  finally geo.Free end;
 
207
end;
 
208
 
 
209
end.