2
// This unit is part of the GLScene Engine https://github.com/glscene
5
Miscelaneous functions used by DCE (Dynamic Collision Engine).
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
22
GLVectorFileObjects, GLEllipseCollision, GLVectorGeometry, GLVectorLists,
23
GLScene, GLTerrainRenderer,GLProxyObjects, GLMultiProxy
26
//Calculate and set the collision range
27
procedure ECSetCollisionRange(var MovePack: TECMovePack);
29
//Set the collider lists to null
30
procedure ECResetColliders(var MovePack: TECMovePack);
32
//Add freeform's octree data
33
procedure ECAddFreeForm(var MovePack: TECMovePack; FreeForm: TGLBaseSceneObject;
34
Solid: Boolean; ObjectID: Integer);
37
procedure ECAddBox(var MovePack: TECMovePack;
38
BoxObj: TGLBaseSceneObject; BoxSize: TAffineVector;
39
Solid: Boolean; ObjectID: Integer);
41
//Add the terrain as a TriMesh
42
procedure ECAddTerrain(var MovePack: TECMovePack;
43
TerrainRenderer: TGLTerrainRenderer; Resolution: Single;
44
Solid: Boolean; ObjectID: Integer);
46
//Add a static ellipsoid
47
procedure ECAddEllipsoid(var MovePack: TECMovePack;
48
ePos, eRadius: TAffineVector;
49
Solid: Boolean; ObjectID: Integer);
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),
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),
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),
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),
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),
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)
76
procedure ECSetCollisionRange(var MovePack: TECMovePack);
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);
85
procedure ECResetColliders(var MovePack: TECMovePack);
87
SetLength(MovePack.TriMeshes,0);
88
SetLength(MovePack.Freeforms,0);
89
SetLength(MovePack.Colliders,0);
92
procedure ECAddFreeForm(var MovePack: TECMovePack; FreeForm: TGLBaseSceneObject;
93
Solid: Boolean; ObjectID: Integer);
97
Master: TGLBaseSceneObject;
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));
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;
115
count := Length(MovePack.Freeforms);
116
with TGLFreeForm(Master).Octree do
118
WalkSphereToLeaf(RootNode, Pos, MovePack.CollisionRange);
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;
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;
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;
148
//Add the box to the triangle list
149
t := Length(MovePack.TriMeshes);
150
SetLength(MovePack.TriMeshes,t+1);
151
ScaleVector(BoxSize,0.5);
158
SetLength(MovePack.TriMeshes[t].Triangles,count);
160
with MovePack.TriMeshes[t] do
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);
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;
176
procedure ECAddTerrain(var MovePack: TECMovePack;
177
TerrainRenderer: TGLTerrainRenderer; Resolution: Single;
178
Solid: Boolean; ObjectID: Integer);
181
function intvec(x,z: Single): TAffineVector;
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];
188
function locabs(x,y,z: Single): TAffineVector;
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];
198
var count,t : Integer;
201
//Add the terrain to the list
202
count := Length(MovePack.TriMeshes);
203
SetLength(MovePack.TriMeshes,count+1);
204
with MovePack.TriMeshes[count] do
206
ObjectInfo.Solid := Solid;
207
ObjectInfo.ObjectID := ObjectID;
209
x := - MovePack.CollisionRange;
210
while x < MovePack.CollisionRange do
213
z := - MovePack.CollisionRange;
214
while z < MovePack.CollisionRange do
218
SetLength(Triangles, t);
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);
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);
246
procedure ECAddEllipsoid(var MovePack: TECMovePack; ePos, eRadius: TAffineVector;
247
Solid: Boolean; ObjectID: Integer);
251
r := MaxXYZComponent(eRadius);
252
d1 := VectorDistance2(MovePack.Position,ePos);
253
d2 := sqr(MovePack.CollisionRange + r);
254
if d1 > d2 then exit;
256
//Add possible collider
257
count := Length(MovePack.Colliders);
258
SetLength(MovePack.Colliders,count+1);
259
with MovePack.Colliders[count] do
263
ObjectInfo.Solid := Solid;
264
ObjectInfo.ObjectID := ObjectID;