LZScene

Форк
0
/
GLDCEMisc.pas 
270 строк · 8.9 Кб
1
//
2
// This unit is part of the GLScene Engine https://github.com/glscene
3
//
4
{
5
  Miscelaneous functions used by DCE (Dynamic Collision Engine).
6

7
   History :  
8
     10/11/12 - PW - Added CPP compatibility: changed vector arrays to records
9
     30/03/07 - DaStr - Added $I GLScene.inc
10
     23/01/05 - LucasG - Code reorganized, many fixes and some new features
11
     03/09/04 - LucasG - First release
12
     29/07/04 - LucasG - Creation
13
   
14
}
15
unit GLDCEMisc;
16

17
interface
18

19
{$I GLScene.inc}
20

21
uses
22
  GLVectorFileObjects, GLEllipseCollision, GLVectorGeometry, GLVectorLists,
23
  GLScene, GLTerrainRenderer,GLProxyObjects, GLMultiProxy
24
  , GLVectorTypes;
25

26
//Calculate and set the collision range
27
procedure ECSetCollisionRange(var MovePack: TECMovePack);
28

29
//Set the collider lists to null
30
procedure ECResetColliders(var MovePack: TECMovePack);
31

32
//Add freeform's octree data
33
procedure ECAddFreeForm(var MovePack: TECMovePack; FreeForm: TGLBaseSceneObject;
34
  Solid: Boolean; ObjectID: Integer);
35

36
//Add a TriMesh box
37
procedure ECAddBox(var MovePack: TECMovePack;
38
  BoxObj: TGLBaseSceneObject; BoxSize: TAffineVector;
39
  Solid: Boolean; ObjectID: Integer);
40

41
//Add the terrain as a TriMesh
42
procedure ECAddTerrain(var MovePack: TECMovePack;
43
  TerrainRenderer: TGLTerrainRenderer; Resolution: Single;
44
  Solid: Boolean; ObjectID: Integer);
45

46
//Add a static ellipsoid
47
procedure ECAddEllipsoid(var MovePack: TECMovePack;
48
  ePos, eRadius: TAffineVector;
49
  Solid: Boolean; ObjectID: Integer);
50

51

52
const
53
    DCEBox: array [0..35] of TAffineVector = (
54
      (X: 1; Y:-1; Z:-1),  (X: 1; Y: 1; Z:-1),  (X: 1; Y:-1; Z: 1),
55
      (X: 1; Y: 1; Z:-1),  (X: 1; Y: 1; Z: 1),  (X: 1; Y:-1; Z: 1),
56

57
      (X: 1; Y: 1; Z:-1),  (X:-1; Y: 1; Z:-1),  (X:-1; Y: 1; Z: 1),
58
      (X: 1; Y: 1; Z: 1),  (X: 1; Y: 1; Z:-1),  (X:-1; Y: 1; Z: 1),
59

60
      (X:-1; Y: 1; Z: 1),  (X:-1; Y:-1; Z: 1),  (X: 1; Y:-1; Z: 1),
61
      (X: 1; Y: 1; Z: 1),  (X:-1; Y: 1; Z: 1),  (X: 1; Y:-1; Z: 1),
62

63
      (X:-1; Y:-1; Z: 1),  (X:-1; Y: 1; Z: 1),  (X:-1; Y: 1; Z:-1),
64
      (X:-1; Y:-1; Z:-1),  (X:-1; Y:-1; Z: 1),  (X:-1; Y: 1; Z:-1),
65

66
      (X: 1; Y:-1; Z: 1),  (X:-1; Y:-1; Z: 1),  (X: 1; Y:-1; Z:-1),
67
      (X:-1; Y:-1; Z: 1),  (X:-1; Y:-1; Z:-1),  (X: 1; Y:-1; Z:-1),
68

69
      (X: 1; Y: 1; Z:-1),  (X: 1; Y:-1; Z:-1),  (X:-1; Y: 1; Z:-1),
70
      (X: 1; Y:-1; Z:-1),  (X:-1; Y:-1; Z:-1),  (X:-1; Y: 1; Z:-1)
71

72
    );
73

74
implementation
75

76
procedure ECSetCollisionRange(var MovePack: TECMovePack);
77
var  N: TAffineVector;
78
begin
79
  N.V[0] := Abs(MovePack.Velocity.V[0]) + Abs(MovePack.Gravity.V[0]) + (MovePack.Radius.V[0]);
80
  N.V[1] := Abs(MovePack.Velocity.V[1]) + Abs(MovePack.Gravity.V[1]) + (MovePack.Radius.V[1]);
81
  N.V[2] := Abs(MovePack.Velocity.V[2]) + Abs(MovePack.Gravity.V[2]) + (MovePack.Radius.V[2]);
82
  MovePack.CollisionRange := MaxXYZComponent(N);
83
end;
84

85
procedure ECResetColliders(var MovePack: TECMovePack);
86
begin
87
  SetLength(MovePack.TriMeshes,0);
88
  SetLength(MovePack.Freeforms,0);
89
  SetLength(MovePack.Colliders,0);
90
end;
91

92
procedure ECAddFreeForm(var MovePack: TECMovePack; FreeForm: TGLBaseSceneObject;
93
  Solid: Boolean; ObjectID: Integer);
94
var
95
  i, count : Integer;
96
  Pos: TVector;
97
  Master: TGLBaseSceneObject;
98
  d1,d2: Single;
99
begin
100
  Master := FreeForm;
101
  if Master is TGLFreeFormProxy then
102
    Master := TGLFreeFormProxy(Master).MasterObject;
103
  if Master is TGLMultiProxy then
104
    if TGLMultiProxy(Master).MasterObjects.Count > 0 then
105
      Master := TGLMultiProxy(Master).MasterObjects[0].MasterObject;
106
  Assert((Master is TGLFreeForm), 'Object must be freeform, freeformproxy or freeformbased Multiproxy.');
107
  Assert(Assigned(TGLFreeForm(Master).Octree), 'Octree must have been prepared and setup before use.');
108
  SetVector(Pos,  FreeForm.AbsoluteToLocal(MovePack.Position));
109

110
  //Is in boundingsphere?
111
  d1 := VectorDistance2(MovePack.Position,AffineVectorMake(FreeForm.AbsolutePosition));
112
  d2 := sqr(MovePack.CollisionRange + Freeform.BoundingSphereRadius);
113
  if d1 > d2 then exit;
114

115
  count := Length(MovePack.Freeforms);
116
  with TGLFreeForm(Master).Octree do
117
  begin
118
    WalkSphereToLeaf(RootNode, Pos, MovePack.CollisionRange);
119

120
    if not Assigned(resultarray) then exit;
121
    //Copy the result array
122
    SetLength(MovePack.Freeforms,count+1);
123
    SetLength(MovePack.Freeforms[count].OctreeNodes, Length(resultarray));
124
    for i := 0 to High(resultarray) do
125
      MovePack.Freeforms[count].OctreeNodes[i] := resultarray[i];
126
    //Reference to this octree
127
    MovePack.Freeforms[count].triangleFiler := @triangleFiler;
128
    MovePack.Freeforms[count].ObjectInfo.AbsoluteMatrix := Freeform.AbsoluteMatrix;
129
    MovePack.Freeforms[count].ObjectInfo.Solid := Solid;
130
    MovePack.Freeforms[count].ObjectInfo.ObjectID := ObjectID;
131
    MovePack.Freeforms[count].InvertedNormals := TGLFreeForm(Master).NormalsOrientation = mnoInvert;
132
  end;
133
end;
134

135
procedure ECAddBox(var MovePack: TECMovePack;
136
  BoxObj: TGLBaseSceneObject; BoxSize: TAffineVector;
137
  Solid: Boolean; ObjectID: Integer);
138
var t,count,i : Integer;
139
    p1, p2, p3: TAffineVector;
140
    BoxRadius,d1,d2: Single;
141
begin
142

143
  BoxRadius := MaxXYZComponent(BoxSize)*MaxXYZComponent(BoxObj.Scale.AsAffineVector);
144
  d1 := VectorDistance2(MovePack.Position,AffineVectorMake(BoxObj.AbsolutePosition));
145
  d2 := sqr(MovePack.CollisionRange + BoxRadius);
146
  if d1 > d2 then exit;
147

148
  //Add the box to the triangle list
149
  t := Length(MovePack.TriMeshes);
150
  SetLength(MovePack.TriMeshes,t+1);
151
  ScaleVector(BoxSize,0.5);
152
  count := 0;
153
  i := 0;
154
  while i < 36 do
155
  begin
156

157
    count := count + 1;
158
    SetLength(MovePack.TriMeshes[t].Triangles,count);
159

160
    with MovePack.TriMeshes[t] do
161
    begin
162
      p1 := DCEBox[i]; ScaleVector(p1,BoxSize); p1 := BoxObj.LocalToAbsolute(p1);
163
      p2 := DCEBox[i+1]; ScaleVector(p2,BoxSize); p2 := BoxObj.LocalToAbsolute(p2);
164
      p3 := DCEBox[i+2]; ScaleVector(p3,BoxSize); p3 := BoxObj.LocalToAbsolute(p3);
165
      i := i + 3;
166
      SetVector(Triangles[count-1].p1, p1);
167
      SetVector(Triangles[count-1].p2, p2);
168
      SetVector(Triangles[count-1].p3, p3);
169
      ObjectInfo.Solid := Solid;
170
      ObjectInfo.ObjectID := ObjectID;
171
    end;
172

173
  end;
174
end;
175

176
procedure ECAddTerrain(var MovePack: TECMovePack;
177
  TerrainRenderer: TGLTerrainRenderer; Resolution: Single;
178
  Solid: Boolean; ObjectID: Integer);
179

180

181
  function intvec(x,z: Single): TAffineVector;
182
  begin
183
    result.V[0] := x + MovePack.Position.V[0];
184
    result.V[1] := 0 + MovePack.Position.V[1];
185
    result.V[2] := z + MovePack.Position.V[2];
186
  end;
187

188
  function locabs(x,y,z: Single): TAffineVector;
189
  begin
190
    //result := TerrainRenderer.LocalToAbsolute(AffineVectorMake(x,y,z));
191
    //result := AffineVectorMake(x,y,z);
192
    result.V[0] := x + MovePack.Position.V[0];
193
    result.V[1] := y + TerrainRenderer.AbsolutePosition.V[1];
194
    result.V[2] := z + MovePack.Position.V[2];
195
  end;
196

197

198
var count,t : Integer;
199
    x,y,z: Single;
200
begin
201
  //Add the terrain to the list
202
  count := Length(MovePack.TriMeshes);
203
  SetLength(MovePack.TriMeshes,count+1);
204
  with MovePack.TriMeshes[count] do
205
  begin
206
    ObjectInfo.Solid := Solid;
207
    ObjectInfo.ObjectID := ObjectID;
208
    t := 0;
209
    x := - MovePack.CollisionRange;
210
    while x < MovePack.CollisionRange do
211
    begin
212

213
      z := - MovePack.CollisionRange;
214
      while z < MovePack.CollisionRange do
215
      begin
216
        //Add 2 triangles
217
        t := t + 2;
218
        SetLength(Triangles, t);
219

220
        //Tri 1
221
        y := TerrainRenderer.InterpolatedHeight(intvec(x,z));
222
        Triangles[t-2].p1 := locabs(x,y,z);
223
        y := TerrainRenderer.InterpolatedHeight(intvec(x,z+Resolution));
224
        Triangles[t-2].p2 := locabs(x,y,z+Resolution);
225
        y := TerrainRenderer.InterpolatedHeight(intvec(x+Resolution,z));
226
        Triangles[t-2].p3 := locabs(x+Resolution,y,z);
227

228
        //Tri 2
229
        y := TerrainRenderer.InterpolatedHeight(intvec(x+Resolution,z+Resolution));
230
        Triangles[t-1].p1 := locabs(x+Resolution,y,z+Resolution);
231
        y := TerrainRenderer.InterpolatedHeight(intvec(x+Resolution,z));
232
        Triangles[t-1].p2 := locabs(x+Resolution,y,z);
233
        y := TerrainRenderer.InterpolatedHeight(intvec(x,z+Resolution));
234
        Triangles[t-1].p3 := locabs(x,y,z+Resolution);
235

236
        z := z + Resolution;
237
      end;
238

239
      x := x + Resolution;
240
    end;
241

242
  end;
243
end;
244

245

246
procedure ECAddEllipsoid(var MovePack: TECMovePack; ePos, eRadius: TAffineVector;
247
  Solid: Boolean; ObjectID: Integer);
248
var count : Integer;
249
    d1, d2, r: single;
250
begin
251
  r := MaxXYZComponent(eRadius);
252
  d1 := VectorDistance2(MovePack.Position,ePos);
253
  d2 := sqr(MovePack.CollisionRange + r);
254
  if d1 > d2 then exit;
255

256
  //Add possible collider
257
  count := Length(MovePack.Colliders);
258
  SetLength(MovePack.Colliders,count+1);
259
  with MovePack.Colliders[count] do
260
  begin
261
    Position := ePos;
262
    Radius := eRadius;
263
    ObjectInfo.Solid := Solid;
264
    ObjectInfo.ObjectID := ObjectID;
265
  end;
266

267
end;
268

269

270
end.
271

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.