Subversion Repositories spacemission

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4 daniel-mar 1
unit colli3DX;
2
 
3
{$include DelphiXcfg.inc}
4
 
5
 
6
//*************************************************************************
7
//*                                                                       *
8
//*  TCollisionTester3DX  vs 1.3                                          *
9
//*                                                                       *
10
//*************************************************************************
11
//
12
// This Delphi 4, 5, 6 component is CopyRight:
13
//
14
// Henrik Fabricius, August 1999, March 2000, June 2002
15
// http://users.cybercity.dk/~bbl6194/delphi3dx.htm
16
// E-mail: henrik_og_bodil@vip.cybercity.dk
17
//
18
// You may use this component for free on the following conditions:
19
// 1) this text must remain part of the unit.
20
// 2) Any proposals for changes or improvements should be addressed directly to
21
//    the copyright owner Henrik Fabricius
22
// 3) The use of this component is on your own risk. The software is provided
23
//    as is without any garanties and warranty. The CopyRight Owner is not
24
//    responsible for any damage or losses of any kind caused by the use of this
25
//    software or the software it is intended to be used with.
26
//
27
// To place a link for down-loads of this component on your homepage
28
// please place a link to the Delphi3DX page where the latest version
29
// is available.
30
//
31
// To use this component you must have
32
// 1) Delphi 4, 5 or 6
33
// 2) MS-DirectX 6.0 or higher
34
// 3) the DelphiX components from Hori in Japan
35
//
36
// MS-DirectX is a trademark of the Microsoft Corporation
37
// Delphi 4, 5 and 6 is a trademark of the Inprise Corporation
38
//
39
// Use this component to check for collisions between 3D objects in
40
// Direct3D games.
41
// Place your 3D-objects in a world described by :
42
// - DXDrawUsed -
43
//
44
// Group the 3D-objects in series with different material
45
// or functional properties
46
// The 3D-object series are named by the property:
47
// - Indexof3DSeries -
48
// 3D-objects are named by the property :
49
// - Indexof3Dobject -
50
// A 3D-object consist of one or more 3D-elements named by the property :
51
// - Indexof3DElement -
52
//
53
// Surround each of your 3D elements by at least one collision object
54
// which must be a member of the following primitives :
55
// - box3D - sphere3D - ellipsoid3D - cylinder3D - conus3D -
56
// available CollOrientations are :
57
// - Symmetric_X - Symmetric_Y - Symmetric_Z -
58
// available material properties are :
59
// - solid3D - water3D - air3D
60
// the size of the small end of the conus is described by the property
61
// - PercentLeftatTop -
62
// a negative value means that the top is downwards
63
// available functional properties are :
64
// - Pickable - Shootable - Fixed3DObject
65
// Add each object by specifying :
66
// - FrameSeries - NextAddMesh - CoverWholeMesh -
67
// - IndexOf3DSeries - IndexOf3DObject - IndexOf3DElement -
68
// if coverWholeMesh is false then specify a box containing the part of the
69
// 3D object which should be covered by the coll object by the commands
70
// - BoxPartMin(x,y,z) - BoxPartMax(x,y,z) -
71
// Finally add the collision object by executing the command
72
// - AddCollisionObject -
73
//
74
// Bullets are described by the following properties :
75
// - BulletRadius - BulletRange - BulletFrame - LongShots -
76
// LongShots moves with a unlimited speed reaching the objects immediately
77
//
78
// The actor is described by :
79
// - FrontDistance - HeadRadius -
80
//
81
// The camera-frame and the bullet-frames move each time the move command
82
// is used in the main program.
83
// Execute the following commands prior to each move command :
84
//  - GetOldEyePos - GetOldBulletPos -
85
// The collisionTester needs this information to test for a possible collision
86
// in between the starting and the ending points of the Eye/bullet
87
//
88
// Test for collision with the following function calls :
89
// - if CollisionTester3DX1.Collision then ..
90
// - if CollisionTester3DX1.BulletCollision then ..
91
// On collision read the HitLinkNr and the properties of the collision object
92
//
93
// Destroy 3D collisionObjects by specifying :
94
//  - NextDestroyNr - IndexOf3DSeries -
95
// and the executing command DestroyCollisionObject
96
//
97
// Initialize the collisionTester with the command :
98
// - CollisionTester3DX1.ZeroSetIt -
99
// This must always be done when DXDraw is initialized
100
//
101
// To install the component:
102
// 1) place this unit and the dcr file in the same directory as DelphiX
103
// 2) In Delphi you must click on Component - Install Component
104
// 3) Select the colli3DX.pas file and choose the Samples package to install it
105
// 4) Rebuild the library
106
// 5) Look for a new icon with a bomb on the page named DelphiX
107
//
108
// Tutorial programs are available for down-load at
109
// http://users.cybercity.dk/~bbl6194/delphi3dx.htm
110
//
111
// Good Luck
112
// Henrik Fabricius
113
//
114
//
115
//****************************************************************************
116
 
117
 
118
 
119
interface
120
 
121
uses
122
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
123
  StdCtrls, DXClass, DXDraws,
124
{$IfDef StandardDX}
125
  DirectDraw, Direct3D, Direct3DRM;
126
{$Else}
127
  DirectX;
128
{$EndIf}
129
 
130
Type
131
  Tshapes3D = (box3D, sphere3D, ellipsoid3D, cylinder3D, conus3D);
132
  Tmaterials3D = (solid3D, water3D, air3D);
133
  TOrientation3D = (symmetric_x, symmetric_y, symmetric_z);
134
  TFrames3D = Array of Array of IDirect3DRMFrame;
135
 
136
  TCollisionTester3DX = class(TComponent)
137
  private
138
    {private declarations}
139
    FDXDrawUsed       : TDXDraw;
140
    FFrameSeries      : TFrames3D;
141
    FNextAddMesh      : IDirect3DRMMesh;
142
    FBulletFrame      : IDirect3DRMFrame;
143
    FBoxPartMin       : TD3DVector;
144
    FBoxPartMax       : TD3DVector;
145
    FOldBulletPosition: TD3DVector;
146
    FOldEyePosition   : TD3DVector;
147
 
148
    FNrOfSeries        : integer;
149
    FSeriesIndex       : integer;
150
    FSeriesNr          : integer;
151
    FOrientation3D     : TOrientation3D;
152
    Fshape3D           : Tshapes3D;
153
    Fmaterial3D        : Tmaterials3D;
154
    FPercentLeftAtTop  : integer;
155
    Fbullet_hitLinknr  : integer;
156
    FIndexOf3DObject   : integer;
157
    FIndexOf3DElement  : integer;
158
    FNextDestroyNr     : integer;
159
    FNextAllOfMesh     : Boolean;
160
    FFrontDistance     : integer;
161
    FBulletRange       : integer;
162
    FBulletRadius      : integer;
163
    FHeadRadius        : integer;
164
    FFixed3DObject     : Boolean;
165
    FShootable         : Boolean;
166
    FLongShots         : Boolean;
167
    FPickable          : Boolean;
168
    FCheckAllCollObj   : Boolean;
169
 
170
    Fcoll_Nr_Objects  : Array of integer;
171
    FSeriesIndex_for_SeriesNr : Array of integer;
172
 
173
    FNrinFrameSeries  : Array of Array of integer;
174
    Fcoll_orientation : Array of Array of TOrientation3D;
175
    Fcoll_shape       : Array of Array of Tshapes3D;
176
    Fcoll_material    : Array of Array of Tmaterials3D;
177
    Fcoll_box_min     : Array of Array of TD3DVector;
178
    Fcoll_box_max     : Array of Array of TD3DVector;
179
    Fcoll_radius      : Array of Array of TD3DValue;
180
    Fcoll_frac_at_top : Array of Array of TD3DValue;
181
    Fcoll_shootable   : Array of Array of boolean;
182
    Fcoll_Pickable    : Array of Array of boolean;
183
    Fcoll_Fixed3D     : Array of Array of boolean;
184
    Fcoll_objectNr    : Array of Array of integer;
185
 
186
    procedure SetOrientation3D(Value : TOrientation3D);
187
    procedure SetShape3D(Value: TShapes3D);
188
    procedure SetMaterial3D(Value: Tmaterials3D);
189
    procedure SetPercentLeftatTop(Value: integer);
190
    procedure SetIndexOf3DObject(Value : integer);
191
    procedure SetIndexOf3DElement(Value : integer);
192
    procedure SetIndexOf3DSeries(Value : integer);
193
    procedure SetNextDestroyNr(Value : Integer);
194
    procedure SetBulletRadius(Value : Integer);
195
    procedure SetHeadRadius(Value : Integer);
196
    procedure SetFrontDistance(Value : Integer);
197
    procedure SetBulletRange(Value : Integer);
198
    function  add_space_for_one_more : boolean;
199
    procedure GetTheBox;
200
    procedure AddBox;
201
    procedure AddSphere;
202
    procedure AddCylinder;
203
    procedure AddConus;
204
    procedure AddEllipsoid;
205
 
206
    procedure MakeNewSeries;
207
    procedure Destroy_empty_series(SeriesNr : integer);
208
    function  GetSeriesNr(Nr : integer): integer;
209
    procedure remove_collision_object(seriesNr, Value : integer);
210
    function  CheckForSeriesIndex(indexnow : integer): boolean;
211
    procedure ListDataForCollObject;
212
    function  coll_test_box(coll_nr : byte;
213
                           old_attacker_position, attacker_position : TD3DVector;
214
                           bullet_radius : TD3DValue; longshot : boolean): boolean;
215
    function  coll_test_cylinder(coll_nr : byte;
216
                           old_attacker_position, attacker_position : TD3DVector;
217
                           bullet_radius : TD3DValue; longshot : boolean): boolean;
218
    function  coll_test_sphere(coll_nr : byte;
219
                           old_attacker_position,
220
                           attacker_position : TD3DVector;
221
                           bullet_radius : TD3Dvalue; longshot : boolean): boolean;
222
    function  coll_test_ellipsoid(coll_nr : byte;
223
                           old_attacker_position, attacker_position : TD3DVector;
224
                           bullet_radius : TD3DValue; longshot : boolean): boolean;
225
    function  coll_test_conus(coll_nr : byte;
226
                           old_attacker_position, attacker_position : TD3DVector;
227
                           bullet_radius : TD3DValue; longshot : boolean): boolean;
228
 
229
  protected
230
 
231
  public
232
    Constructor Create(AOwner : TComponent); override;
233
    destructor Destroy; override;
234
 
235
    property DXDrawUsed       : TDXDraw write FDXDrawUsed stored false;
236
    property FrameSeries      : TFrames3D write FFrameSeries stored false;
237
    property NextAddMesh      : IDirect3DRMMesh write FNextAddMesh stored false;
238
    property BulletFrame      : IDirect3DRMFrame write FBulletFrame stored false;
239
 
240
    procedure ZeroSetIt;
241
    procedure BoxPartMin(xval, yval, zval: TD3DValue);
242
    procedure BoxPartMax(xval, yval, zval: TD3DValue);
243
    procedure GetOldBulletPos;
244
    procedure GetOldEyePos;
245
 
246
    function  HitLinkNr: integer;
247
    function  DestroyCollisionObject: boolean;
248
    procedure AddCollisionObject;
249
    function  Collision: boolean;
250
    function  Bulletcollision: boolean;
251
    function  BulletDead : boolean;
252
 
253
 
254
  published
255
 
256
    property BulletRadius     : Integer read FBulletRadius write SetBulletRadius
257
                                default 0;
258
    property BulletRange      : Integer read FbulletRange write SetBulletRange
259
                                Default 100;
260
    property CollisionCheckAll: Boolean read FCheckAllCollObj
261
                                write FCheckAllCollObj  Default true;
262
    property CollOrientation  : TOrientation3D read FOrientation3D
263
                                write SetOrientation3D default symmetric_y;
264
    property CollObjectType   : Tshapes3D read Fshape3D write SetShape3D
265
                                default box3D;
266
    property CollObjMaterial  : Tmaterials3D read Fmaterial3D write SetMaterial3D
267
                                default solid3D;
268
    property CoverWholeMesh   : boolean read FNextAllOfMesh
269
                                write FNextAllOfMesh default true;
270
    Property Fixed3DObject    : boolean read FFixed3DObject
271
                                write FFixed3DObject default true;
272
    property FrontDistance    : Integer read FFrontDistance
273
                                write SetFrontDistance default 0;
274
    property HeadRadius       : integer read FHeadRadius write SetHeadRadius
275
                                default 0;
276
    property IndexOf3DSeries  : integer read FSeriesIndex
277
                                write SetIndexOf3DSeries default 0;
278
    property IndexOf3DObject  : integer read FIndexOf3DObject
279
                                write SetIndexOf3DObject default 0;
280
    property IndexOf3DElement : integer read FIndexOf3DElement
281
                                write SetIndexOf3DElement default 0;
282
    property NextDestroyNr    : Integer read FNextDestroyNr
283
                                write SetNextDestroyNr default 0;
284
    Property PercentLeftAtTop : integer read FPercentLeftAtTop
285
                                write SetPercentLeftAtTop default 0;
286
    Property Pickable         : Boolean read FPickable write FPickable
287
                                default false;
288
    Property Shootable        : boolean read FShootable write FShootable
289
                                Default false;
290
    Property LongShots        : boolean read FLongShots write FLongShots
291
                                Default false;
292
 
293
 
294
  end; //end of Class
295
 
296
 
297
 
298
//Registering of the Component
299
Procedure Register;
300
 
301
 
302
implementation
303
 
304
 
305
 
306
procedure Register;
307
begin
308
  //Register the component together with the DelphiX components from Hori
309
  RegisterComponents('DelphiX', [TCollisionTester3DX]);
310
end; //end of Register
311
 
312
 
313
constructor TCollisionTester3DX.Create(AOwner : TComponent);
314
begin
315
  inherited Create(AOwner);
316
  //The constructor always clears the storage it allocates for a new object
317
  //Hence there is no need to initialize fields except to nonzero or nonempty
318
  //values
319
  FDXDrawUsed := nil;
320
  FFrameSeries := nil;
321
  FNextAddMesh := nil;
322
  FBulletFrame := nil;
323
 
324
  FOrientation3D := symmetric_y;
325
  FShape3D := box3D;
326
  FMaterial3D := solid3D;
327
  FBulletRange := 100;
328
  FNrOfSeries := 0;
329
  setlength(FSeriesIndex_for_SeriesNr, 0);
330
  setlength(FColl_nr_objects, 0);
331
  setlength(FNrinFrameSeries, 0);
332
  setlength(Fcoll_shape, 0);
333
  setlength(Fcoll_box_min, 0);
334
  setlength(Fcoll_box_max, 0);
335
  setlength(Fcoll_radius, 0);
336
  setlength(Fcoll_frac_at_top, 0);
337
  setlength(Fcoll_objectnr, 0);
338
  setlength(Fcoll_shootable, 0);
339
  setlength(Fcoll_pickable, 0);
340
  setlength(Fcoll_orientation, 0);
341
  setlength(Fcoll_material, 0);
342
  setlength(Fcoll_Fixed3D, 0);
343
 
344
end; //end of creation
345
 
346
 
347
 
348
 
349
 
350
 
351
 
352
destructor TCollisionTester3DX.Destroy;
353
begin
354
  //destroy any embedded objects and free resources allocated by the objects
355
  FnrinFrameSeries := nil;
356
  Fcoll_shape := nil;
357
  Fcoll_box_min := nil;
358
  Fcoll_box_max := nil;
359
  Fcoll_radius := nil;
360
  Fcoll_frac_at_top := nil;
361
  Fcoll_objectnr := nil;
362
  Fcoll_shootable := nil;
363
  Fcoll_pickable := nil;
364
  Fcoll_orientation := nil;
365
  Fcoll_material := nil;
366
  Fcoll_Fixed3D := nil;
367
  FSeriesIndex_for_SeriesNr := nil;
368
  Fcoll_nr_objects := nil;
369
 
370
  inherited Destroy;
371
end; //end of Destroy
372
 
373
 
374
 
375
 
376
procedure TCollisionTester3DX.ZeroSetIt;
377
begin
378
  //initialises the dynamic arrays
379
  FnrinFrameSeries := nil;
380
  Fcoll_shape := nil;
381
  Fcoll_box_min := nil;
382
  Fcoll_box_max := nil;
383
  Fcoll_radius := nil;
384
  Fcoll_frac_at_top := nil;
385
  Fcoll_objectnr := nil;
386
  Fcoll_shootable := nil;
387
  Fcoll_pickable := nil;
388
  Fcoll_orientation := nil;
389
  Fcoll_material := nil;
390
  Fcoll_Fixed3D := nil;
391
  FSeriesIndex_for_SeriesNr := nil;
392
  Fcoll_nr_objects := nil;
393
 
394
  FDXDrawUsed := nil;
395
  FFrameSeries := nil;
396
  FNextAddMesh := nil;
397
  FBulletFrame := nil;
398
 
399
  FOrientation3D := symmetric_y;
400
  FShape3D := box3D;
401
  FMaterial3D := solid3D;
402
  FBulletRange := 100;
403
  FNrOfSeries := 0;
404
  setlength(FSeriesIndex_for_SeriesNr, 0);
405
  setlength(FColl_nr_objects, 0);
406
  setlength(FNrinFrameSeries, 0);
407
  setlength(Fcoll_shape, 0);
408
  setlength(Fcoll_box_min, 0);
409
  setlength(Fcoll_box_max, 0);
410
  setlength(Fcoll_radius, 0);
411
  setlength(Fcoll_frac_at_top, 0);
412
  setlength(Fcoll_objectnr, 0);
413
  setlength(Fcoll_shootable, 0);
414
  setlength(Fcoll_pickable, 0);
415
  setlength(Fcoll_orientation, 0);
416
  setlength(Fcoll_material, 0);
417
  setlength(Fcoll_Fixed3D, 0);
418
 
419
end;  //end of ZeroSetIt
420
 
421
 
422
 
423
 
424
function TcollisionTester3DX.HitLinkNr: integer;
425
begin
426
  result := Fbullet_hitlinknr;
427
end; //end of HitLinkNr
428
 
429
 
430
 
431
procedure TCollisionTester3DX.ListDataForCollObject;
432
var
433
  Nr : integer;
434
begin
435
  Nr := FBullet_HitLinkNr;
436
 
437
  CollObjectType   := Fcoll_shape[FSeriesNr, Nr];
438
  CollObjMaterial  := Fcoll_material[FSeriesNr, Nr];
439
  Fixed3DObject    := Fcoll_Fixed3D[FSeriesNr, Nr];
440
  CollOrientation  := Fcoll_orientation[FSeriesNr, Nr];
441
  IndexOf3DObject  := Fcoll_objectNr[FSeriesNr, Nr];
442
  IndexOf3DSeries  := FSeriesIndex;
443
  IndexOf3DElement := FNrinFrameSeries[FSeriesNr, Nr];
444
  Pickable         := Fcoll_pickable[FSeriesNr, Nr];
445
  Shootable        := Fcoll_shootable[FseriesNr, Nr];
446
 
447
end; //end of ListDataForCollObject
448
 
449
 
450
 
451
 
452
procedure TcollisionTester3DX.SetPercentLeftAtTop(Value : Integer);
453
begin
454
  //value can not be negative
455
  if (FPercentLeftAtTop <> Value) and (Value >= 0)
456
  then
457
    FPercentLeftAtTop := value;
458
end; //end of SetPercentLeftAtTop
459
 
460
 
461
 
462
 
463
procedure TcollisionTester3DX.SetOrientation3D(Value : TOrientation3D);
464
begin
465
  if FOrientation3D <> Value
466
  then
467
    FOrientation3D := Value;
468
end; //end setorientation3D
469
 
470
 
471
procedure TcollisionTester3DX.SetShape3D(Value : Tshapes3D);
472
begin
473
  if Fshape3D <> Value
474
  then
475
    Fshape3D := Value;
476
end; //end setshapes3D
477
 
478
 
479
 
480
procedure TcollisionTester3DX.SetMaterial3D(Value : Tmaterials3D);
481
begin
482
  if Fmaterial3D <> Value
483
  then
484
    Fmaterial3D := Value;
485
end; //end setshapes3D
486
 
487
 
488
 
489
procedure TCollisionTester3DX.SetIndexOf3DObject(Value : integer);
490
begin
491
  //Index can not be negative
492
  if (FIndexOf3DObject <> Value) and (Value >= 0)
493
  then
494
    FIndexOf3DObject := value;
495
end; //end setIndexOf3DObject
496
 
497
 
498
procedure TCollisionTester3DX.SetIndexOf3DElement(Value : integer);
499
begin
500
  //Index can not be negative
501
  if (FIndexOf3DElement <> Value) and (Value >= 0)
502
  then
503
    FIndexOf3DElement := value;
504
end; //end setIndexOf3DElement
505
 
506
 
507
 
508
procedure TCollisionTester3DX.SetIndexOf3DSeries(Value : integer);
509
begin
510
  //Index can not be negative
511
  if (FSeriesIndex <> Value) and (Value >= 0)
512
  then
513
    FSeriesIndex := value;
514
end; //end of SetIndexOf3DSeries
515
 
516
 
517
 
518
 
519
procedure TCollisionTester3DX.SetNextDestroyNr(Value : integer);
520
begin
521
  //Index can not be negative
522
  if (FNextDestroyNr <> Value) and (Value >= 0)
523
  then
524
    FNextDestroyNr := value;
525
end; //end of SetNextDestroyNr
526
 
527
 
528
 
529
 
530
procedure TCollisionTester3DX.SetBulletRadius(Value : Integer);
531
begin
532
  //Radius can not be negative
533
  if (FBulletRadius <> Value) and (Value >= 0)
534
  then
535
    FBulletRadius := value;
536
end; //end of SetBulletRadius
537
 
538
 
539
 
540
procedure TCollisionTester3DX.SetHeadRadius(Value : Integer);
541
begin
542
  //Radius can not be negative
543
  if (FHeadRadius <> Value) and (Value >= 0)
544
  then
545
    FHeadRadius := value;
546
end; //end of SetHeadRadius
547
 
548
 
549
 
550
 
551
procedure TCollisionTester3DX.SetFrontDistance(Value : Integer);
552
begin
553
  //FrontDistance can not be negative
554
  if (FFrontDistance <> Value) and (Value >= 0)
555
  then
556
    FFrontDistance := value;
557
end; //end of SetFrontDistance
558
 
559
 
560
 
561
 
562
procedure TCollisionTester3DX.SetBulletRange(Value : Integer);
563
begin
564
  //BulletRange can not be negative
565
  if (FBulletRange <> Value) and (Value >= 0)
566
  then
567
    FBulletRange := value;
568
end; //end of SetBulletRange
569
 
570
 
571
 
572
 
573
function TcollisionTester3DX.Add_Space_For_One_More: boolean;
574
var
575
  NewNr : integer;
576
begin
577
  //add space for one more element in the present series
578
 
579
  //length of Fcoll_nr_objects and FSeries_nIndex_for_SeriesNr are unchanged
580
  NewNr := Fcoll_nr_objects[FseriesNr] + 1;
581
 
582
  result := true;
583
 
584
  try
585
    SetLength(FNrinFrameSeries[FSeriesNr],  NewNr);
586
    SetLength(Fcoll_shape[FSeriesNr],       NewNr);
587
    SetLength(Fcoll_box_min[FSeriesNr],     NewNr);
588
    SetLength(Fcoll_box_max[FSeriesNr],     NewNr);
589
    SetLength(Fcoll_radius[FSeriesNr],      NewNr);
590
    SetLength(Fcoll_frac_at_top[FSeriesNr], NewNr);
591
    SetLength(Fcoll_objectnr[FSeriesNr],    NewNr);
592
    SetLength(Fcoll_shootable[FSeriesNr],   NewNr);
593
    SetLength(Fcoll_pickable[FSeriesNr],    NewNr);
594
    SetLength(Fcoll_orientation[FSeriesNr], NewNr);
595
    SetLength(Fcoll_material[FSeriesNr],    NewNr);
596
    SetLength(Fcoll_Fixed3D[FSeriesNr],     NewNr);
597
 
598
  except
599
    on EOutOfMemory do
600
    begin
601
      //There is not enough memory available. Free some memory
602
      dec(NewNr);
603
 
604
      copy(FNrinFrameSeries[FseriesNr],  0, NewNr);
605
      copy(Fcoll_shape[FseriesNr],       0, NewNr);
606
      copy(Fcoll_box_min[FSeriesNr],     0, NewNr);
607
      copy(Fcoll_box_max[FSeriesNr],     0, NewNr);
608
      copy(Fcoll_radius[FSeriesNr],      0, NewNr);
609
      copy(Fcoll_frac_at_top[FSeriesNr], 0, NewNr);
610
      copy(Fcoll_objectnr[FSeriesNr],    0, NewNr);
611
      copy(Fcoll_shootable[FSeriesNr],   0, NewNr);
612
      copy(Fcoll_pickable[FSeriesNr],    0, NewNr);
613
      copy(Fcoll_orientation[FSeriesNr], 0, NewNr);
614
      copy(Fcoll_material[FSeriesNr],    0, NewNr);
615
      copy(Fcoll_Fixed3D[FSeriesNr],     0, NewNr);
616
 
617
      result := false;
618
    end;
619
  end;
620
 
621
  //update count of objects in series
622
  Fcoll_nr_objects[FseriesNr] := NewNr;
623
 
624
end; //end of Add_Space_For_One_More
625
 
626
 
627
 
628
 
629
procedure TcollisionTester3DX.MakeNewSeries;
630
begin
631
  inc(FNrOfSeries);
632
 
633
  SetLength(FSeriesIndex_for_SeriesNr, FNrOfSeries);
634
  FSeriesIndex_for_SeriesNr[FNrOfSeries-1] := FSeriesIndex;
635
 
636
  SetLength(Fcoll_nr_objects, FNrOfSeries);
637
  Fcoll_nr_objects[FNrOfSeries-1] := 0;
638
 
639
  SetLength(FNrinFrameSeries,  FNrOfSeries);
640
  SetLength(Fcoll_shape,       FNrOfSeries);
641
  SetLength(Fcoll_box_min,     FNrOfSeries);
642
  SetLength(Fcoll_box_max,     FNrOfSeries);
643
  SetLength(Fcoll_radius,      FNrOfSeries);
644
  SetLength(Fcoll_frac_at_top, FNrOfSeries);
645
  SetLength(Fcoll_objectnr,    FNrOfSeries);
646
  SetLength(Fcoll_shootable,   FNrOfSeries);
647
  SetLength(Fcoll_pickable,    FNrOfSeries);
648
  SetLength(Fcoll_orientation, FNrOfSeries);
649
  SetLength(Fcoll_material,    FNrOfSeries);
650
  SetLength(Fcoll_Fixed3D,     FNrOfSeries);
651
end; //end of MakeNewSeries
652
 
653
 
654
 
655
 
656
procedure TcollisionTester3DX.Destroy_Empty_Series(SeriesNr : integer);
657
var
658
  i, j : integer;
659
begin
660
  if seriesNr < (FNrOfSeries - 1)
661
  then
662
  begin
663
    for i := SeriesNr to (FNrOfSeries - 2) do
664
    begin
665
      FSeriesIndex_for_SeriesNr[i] := FSeriesIndex_for_SeriesNr[i+1];
666
 
667
      SetLength(FNrinFrameSeries[i], Fcoll_Nr_objects[i+1]);
668
      for j := 0 to (Fcoll_Nr_objects[i+1] - 1) do
669
        FNrinFrameSeries[i, j] := FNrinFrameSeries[(i+1), j];
670
 
671
      SetLength(Fcoll_shape[i], Fcoll_Nr_objects[i+1]);
672
      for j := 0 to (Fcoll_Nr_objects[i+1] - 1) do
673
        Fcoll_shape[i, j] := Fcoll_shape[(i+1), j];
674
 
675
      SetLength(Fcoll_box_min[i], Fcoll_Nr_objects[i+1]);
676
      for j := 0 to (Fcoll_Nr_objects[i+1] - 1) do
677
        Fcoll_box_min[i, j] := Fcoll_box_min[(i+1), j];
678
 
679
      SetLength(Fcoll_box_max[i], Fcoll_Nr_objects[i+1]);
680
      for j := 0 to (Fcoll_Nr_objects[i+1] - 1) do
681
        Fcoll_box_max[i, j] := Fcoll_box_max[(i+1), j];
682
 
683
      SetLength(Fcoll_radius[i], Fcoll_Nr_objects[i+1]);
684
      for j := 0 to (Fcoll_Nr_objects[i+1] - 1) do
685
        Fcoll_radius[i, j] := Fcoll_radius[(i+1), j];
686
 
687
      SetLength(Fcoll_frac_at_top[i], Fcoll_Nr_objects[i+1]);
688
      for j := 0 to (Fcoll_Nr_objects[i+1] - 1) do
689
        Fcoll_frac_at_top[i, j] := Fcoll_frac_at_top[(i+1), j];
690
 
691
      SetLength(Fcoll_objectnr[i], Fcoll_Nr_objects[i+1]);
692
      for j := 0 to (Fcoll_Nr_objects[i+1] - 1) do
693
        Fcoll_objectNr[i, j] := Fcoll_objectNr[(i+1), j];
694
 
695
      SetLength(Fcoll_shootable[i], Fcoll_Nr_objects[i+1]);
696
      for j := 0 to (Fcoll_Nr_objects[i+1] - 1) do
697
        Fcoll_shootable[i, j] := Fcoll_shootable[(i+1), j];
698
 
699
      SetLength(Fcoll_pickable[i], Fcoll_Nr_objects[i+1]);
700
      for j := 0 to (Fcoll_Nr_objects[i+1] - 1) do
701
        Fcoll_pickable[i, j] := Fcoll_pickable[(i+1), j];
702
 
703
      SetLength(Fcoll_orientation[i], Fcoll_Nr_objects[i+1]);
704
      for j := 0 to (Fcoll_Nr_objects[i+1] - 1) do
705
        Fcoll_orientation[i, j] := Fcoll_orientation[(i+1), j];
706
 
707
      SetLength(Fcoll_material[i], Fcoll_Nr_objects[i+1]);
708
      for j := 0 to (Fcoll_Nr_objects[i+1] - 1) do
709
        Fcoll_material[i, j] := Fcoll_material[(i+1), j];
710
 
711
      SetLength(Fcoll_Fixed3D[i], Fcoll_Nr_objects[i+1]);
712
      for j := 0 to (Fcoll_Nr_objects[i+1] - 1) do
713
        Fcoll_Fixed3D[i, j] := Fcoll_Fixed3D[(i+1), j];
714
 
715
      Fcoll_nr_objects[i] := Fcoll_nr_objects[i+1];
716
 
717
    end;
718
  end;
719
 
720
  dec(FNrOfSeries);
721
 
722
  FSeriesIndex_For_SeriesNr := copy(FSeriesIndex_for_SeriesNr, 0, FNrOfSeries);
723
  Fcoll_Nr_Objects := copy(Fcoll_Nr_Objects, 0, FNrOfSeries);
724
  FNrinFrameSeries := copy(FNrinFrameSeries, 0, FNrOfSeries);
725
  Fcoll_Shape := copy(Fcoll_Shape, 0, FNrOfSeries);
726
  Fcoll_Box_Min := copy(Fcoll_Box_Min, 0, FNrOfSeries);
727
  Fcoll_Box_Max := copy(Fcoll_Box_Max, 0, FNrOfSeries);
728
  Fcoll_Radius := copy(Fcoll_Radius, 0, FNrOfSeries);
729
  Fcoll_Frac_At_Top := copy(Fcoll_Frac_At_Top, 0, FNrOfSeries);
730
  Fcoll_ObjectNr := copy(Fcoll_ObjectNr, 0, FNrOfSeries);
731
  Fcoll_Shootable := copy(Fcoll_Shootable, 0, FNrOfSeries);
732
  Fcoll_Pickable := copy(Fcoll_Pickable, 0, FNrOfSeries);
733
  Fcoll_orientation := copy(Fcoll_orientation, 0, FNrOfSeries);
734
  Fcoll_Material := copy(Fcoll_Material, 0, FNrOfSeries);
735
  Fcoll_Fixed3D := copy(Fcoll_Fixed3D, 0, FNrOfSeries);
736
end; //end of Destroy_Empty_Series
737
 
738
 
739
 
740
 
741
 
742
 
743
 
744
procedure TcollisionTester3DX.Remove_Collision_Object(SeriesNr, Value : integer);
745
var
746
  i : integer;
747
begin
748
  //Elements in the series which have a higher index than the one removed
749
  //gets a smaller index which is correct when the main program removes the object
750
  for i := 0 to (FColl_nr_objects[SeriesNr] - 1) do
751
  begin
752
    if FNrinFrameSeries[SeriesNr, i] >= value
753
    then
754
      dec(FNrinFrameSeries[SeriesNr, i]);
755
  end;
756
 
757
  for i := Value to (Fcoll_nr_objects[SeriesNr] - 2) do
758
  begin
759
    FNrinFrameSeries[SeriesNr, i]  := FNrinFrameSeries[SeriesNr, (i+1)];
760
    Fcoll_shape[SeriesNr, i]       := Fcoll_shape[SeriesNr, (i+1)];
761
    Fcoll_box_min[SeriesNr, i]     := Fcoll_box_min[SeriesNr, (i+1)];
762
    Fcoll_box_max[SeriesNr, i]     := Fcoll_box_max[SeriesNr, (i+1)];
763
    Fcoll_radius[seriesNr, i]      := Fcoll_radius[SeriesNr, (i+1)];
764
    Fcoll_frac_at_top[SeriesNr, i] := Fcoll_frac_at_top[SeriesNr, (i+1)];
765
    Fcoll_objectnr[SeriesNr, i]    := Fcoll_objectnr[SeriesNr, (i+1)];
766
    Fcoll_shootable[SeriesNr, i]   := Fcoll_shootable[SeriesNr, (i+1)];
767
    Fcoll_Pickable[SeriesNr, i]    := Fcoll_Pickable[SeriesNr, (i+1)];
768
    Fcoll_orientation[SeriesNr, i] := Fcoll_orientation[SeriesNr, (i+1)];
769
    Fcoll_material[SeriesNr, i]    := Fcoll_material[SeriesNr, (i+1)];
770
    Fcoll_Fixed3D[SeriesNr, i]     := Fcoll_Fixed3D[SeriesNr, (i+1)];
771
  end;
772
 
773
  dec(Fcoll_nr_objects[SeriesNr]);
774
 
775
  //remember to reduce the length of Fcoll_frame
776
  FNrinFrameSeries[SeriesNr]  := copy(FNrinFrameSeries[SeriesNr], 0,
777
                                 Fcoll_nr_objects[SeriesNr]);
778
  Fcoll_shape[SeriesNr]       := copy(Fcoll_shape[SeriesNr], 0,
779
                                 Fcoll_nr_objects[SeriesNr]);
780
  Fcoll_box_min[SeriesNr]     := copy(Fcoll_box_min[SeriesNr], 0,
781
                                 Fcoll_nr_objects[SeriesNr]);
782
  Fcoll_box_max[SeriesNr]     := copy(Fcoll_box_max[SeriesNr], 0,
783
                                 Fcoll_nr_objects[SeriesNr]);
784
  Fcoll_radius[SeriesNr]      := copy(Fcoll_radius[SeriesNr], 0,
785
                                 Fcoll_nr_objects[SeriesNr]);
786
  Fcoll_frac_at_top[SeriesNr] := copy(Fcoll_frac_at_top[SeriesNr], 0,
787
                                 Fcoll_nr_objects[SeriesNr]);
788
  Fcoll_objectnr[SeriesNr]    := copy(Fcoll_objectnr[SeriesNr], 0,
789
                                 Fcoll_nr_objects[SeriesNr]);
790
  Fcoll_shootable[SeriesNr]   := copy(Fcoll_shootable[SeriesNr], 0,
791
                                 Fcoll_nr_objects[SeriesNr]);
792
  Fcoll_pickable[SeriesNr]    := copy(Fcoll_pickable[SeriesNr], 0,
793
                                 Fcoll_nr_objects[SeriesNr]);
794
  Fcoll_material[SeriesNr]    := copy(Fcoll_material[SeriesNr], 0,
795
                                 Fcoll_nr_objects[FSeriesNr]);
796
  Fcoll_orientation[SeriesNr] := copy(Fcoll_orientation[SeriesNr], 0,
797
                                 Fcoll_nr_objects[FSeriesNr]);
798
  Fcoll_fixed3D[SeriesNr]     := copy(Fcoll_fixed3D[SeriesNr], 0,
799
                                 Fcoll_nr_objects[SeriesNr]);
800
 
801
end; //end of Remove_Collision_Object
802
 
803
 
804
 
805
 
806
 
807
 
808
 
809
procedure TCollisionTester3DX.GetTheBox;
810
var
811
  box: TD3DRMBOX;
812
begin
813
  if FNextAllOfMesh
814
  then
815
  begin
816
    FNextAddMesh.GetBox(box);
817
    FColl_box_min[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)] := box.min;
818
    FColl_box_max[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)] := box.max;
819
  end
820
  else
821
  begin
822
    FColl_box_min[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)] := FBoxPartMin;
823
    FColl_box_max[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)] := FBoxPartMax;
824
  end;
825
 
826
end;  //end of GetTheBox
827
 
828
 
829
 
830
procedure TCollisionTester3DX.BoxPartMin(xval, yval, zval : TD3DValue);
831
begin
832
  FBoxPartMin.x := xval;
833
  FBoxPartMin.y := yval;
834
  FBoxPartMin.z := zval;
835
end; //end of BoxPartMin
836
 
837
 
838
 
839
 
840
procedure TCollisionTester3DX.BoxPartMax(xval, yval, zval : TD3DValue);
841
begin
842
  FBoxPartMax.x := xval;
843
  FBoxPartMax.y := yval;
844
  FBoxPartMax.z := zval;
845
end; //end of BoxPartMax
846
 
847
 
848
 
849
 
850
 
851
procedure TCollisionTester3DX.AddBox;
852
begin
853
  if add_space_for_one_more
854
  then
855
  begin
856
    GetTheBox;
857
 
858
    Fcoll_objectnr[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]    := FIndexOf3DObject;
859
    Fcoll_shape[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]       := box3D;
860
    FNrinFrameSeries[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]  := FIndexof3Delement;
861
    Fcoll_radius[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]      := 0; //not used
862
    Fcoll_frac_at_top[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)] := 0; //not used
863
    Fcoll_material[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]    := Fmaterial3D;
864
    Fcoll_orientation[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)] := Forientation3D;
865
    Fcoll_shootable[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] -1)]    := Fshootable;
866
    Fcoll_Pickable[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]    := Fpickable;
867
    Fcoll_fixed3D[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]     := FFixed3DObject;
868
  end;
869
end; //end of AddBox
870
 
871
 
872
 
873
 
874
procedure TCollisionTester3DX.AddSphere;
875
begin
876
  if add_space_for_one_more
877
  then
878
  begin
879
    GetTheBox;
880
    Fcoll_objectnr[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]    := FIndexOf3DObject;
881
    Fcoll_shape[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]       := sphere3D;
882
    FNrinFrameSeries[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]  := FIndexof3Delement;
883
    Fcoll_radius[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]      :=
884
     (FColl_box_max[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)].x
885
    - FColl_box_min[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)].x
886
    + FColl_box_max[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)].y
887
    - FColl_box_min[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)].y
888
    + FColl_box_max[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)].z
889
    - FColl_box_min[FSeriesNr, (Fcoll_Nr_objects[FseriesNr] - 1)].z)/2/3;
890
    Fcoll_frac_at_top[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)] := 0; //not used
891
    Fcoll_orientation[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)] := Forientation3D;
892
    Fcoll_material[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]    := Fmaterial3D;
893
    Fcoll_shootable[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]   := Fshootable;
894
    Fcoll_Pickable[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]    := Fpickable;
895
    Fcoll_fixed3D[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]     := FFixed3DObject;
896
  end;
897
 
898
end; //end of AddSphere
899
 
900
 
901
 
902
 
903
 
904
procedure TCollisionTester3DX.Addcylinder;
905
begin
906
  //the sphere cowers whole of the 3D-object
907
  if add_space_for_one_more
908
  then
909
  begin
910
    GetTheBox;
911
 
912
    Fcoll_objectnr[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]    := FIndexOf3DObject;
913
    Fcoll_shape[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]       := cylinder3D;
914
    FNrinFrameSeries[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]  := FIndexof3Delement;
915
    case Forientation3D of
916
    symmetric_x : Fcoll_radius[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]      :=
917
     (FColl_box_max[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)].y
918
    - FColl_box_min[FSeriesNr, (Fcoll_Nr_objects[FseriesNr] - 1)].y
919
    + FColl_box_max[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)].z
920
    - FColl_box_min[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)].z)/2/2;
921
    symmetric_y : Fcoll_radius[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]      :=
922
     (FColl_box_max[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)].x
923
    - FColl_box_min[FSeriesNr, (Fcoll_Nr_objects[FseriesNr] - 1)].x
924
    + FColl_box_max[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)].z
925
    - FColl_box_min[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)].z)/2/2;
926
    symmetric_z : Fcoll_radius[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]      :=
927
     (FColl_box_max[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)].x
928
    - FColl_box_min[FSeriesNr, (Fcoll_Nr_objects[FseriesNr] - 1)].x
929
    + FColl_box_max[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)].y
930
    - FColl_box_min[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)].y)/2/2;
931
    end;
932
 
933
    Fcoll_frac_at_top[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)] := 0; //not used
934
    Fcoll_orientation[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)] := Forientation3D;
935
    Fcoll_material[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]    := Fmaterial3D;
936
    Fcoll_shootable[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]   := Fshootable;
937
    Fcoll_Pickable[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]    := Fpickable;
938
    Fcoll_fixed3D[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]     := FFixed3DObject;
939
  end;
940
end; //end of Addcylinder
941
 
942
 
943
 
944
 
945
procedure TCollisionTester3DX.Addconus;
946
begin
947
  //the conus cowers whole of or part of the 3D-object
948
  //fraction_left_at_top = 0 if sharp tip
949
  if add_space_for_one_more
950
  then
951
  begin
952
    GettheBox;
953
 
954
    Fcoll_objectnr[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]    := FIndexOf3DObject;
955
    Fcoll_shape[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]       := conus3D;
956
    FNrinFrameSeries[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]  := FIndexof3Delement;
957
    Fcoll_radius[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]      :=
958
     (FColl_box_max[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)].x
959
    - FColl_box_min[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)].x
960
    + FColl_box_max[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)].z
961
    - FColl_box_min[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)].z)/2/2;
962
    Fcoll_frac_at_top[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)] := FPercentLeftAtTop/100;
963
    Fcoll_orientation[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)] := Forientation3D;
964
    Fcoll_material[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]    := Fmaterial3D;
965
    Fcoll_shootable[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] -1)]    := Fshootable;
966
    Fcoll_Pickable[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]    := Fpickable;
967
    Fcoll_fixed3D[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]     := FFixed3DObject;
968
  end;
969
end; //end of Addconus
970
 
971
 
972
 
973
 
974
procedure TCollisionTester3DX.AddEllipsoid;
975
begin
976
  if add_space_for_one_more
977
  then
978
  begin
979
    GetTheBox;
980
    Fcoll_objectnr[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]      := FIndexOf3DObject;
981
    Fcoll_shape[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]         := Ellipsoid3D;
982
    FNrinFrameSeries[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]  := FIndexof3Delement;
983
    Fcoll_radius[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]        := 0; //not used
984
    Fcoll_frac_at_top[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]   := 0; //not used
985
    Fcoll_orientation[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)] := Forientation3D;
986
    Fcoll_material[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]      := Fmaterial3D;
987
    Fcoll_shootable[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]     := Fshootable;
988
    Fcoll_Pickable[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]      := Fpickable;
989
    Fcoll_fixed3D[FSeriesNr, (Fcoll_Nr_objects[FSeriesNr] - 1)]       := FFixed3DObject;
990
  end;
991
end; //end of AddEllipsoid
992
 
993
 
994
 
995
 
996
 
997
 
998
 
999
function TcollisionTester3DX.GetSeriesNr(Nr : integer): integer;
1000
var
1001
  NrNow, i : integer;
1002
begin
1003
 
1004
  if FNrOfSeries = 0
1005
  then
1006
    NrNow := 0
1007
  else
1008
  begin
1009
    NrNow := -1;
1010
    for i := 0 to (FNrOfSeries - 1) do
1011
    begin
1012
      if Nr = FSeriesIndex_for_SeriesNr[i]
1013
      then
1014
        NrNow := i;
1015
    end;
1016
 
1017
    if NrNow = -1
1018
    then
1019
      NrNow := FNrOfSeries; //make new series
1020
  end;
1021
 
1022
  if NrNow = FNrOfSeries
1023
  then
1024
    MakeNewSeries;
1025
 
1026
 
1027
  result := NrNow;
1028
 
1029
 
1030
end; //end of GetSeriesNr
1031
 
1032
 
1033
 
1034
 
1035
 
1036
function TcollisionTester3DX.CheckForSeriesIndex(indexnow : integer): boolean;
1037
var
1038
  i : integer;
1039
begin
1040
 
1041
  if FNrOfSeries = 0
1042
  then
1043
    result := false
1044
  else
1045
  begin
1046
    FSeriesNr := -1;
1047
    for i := 0 to (FNrOfSeries - 1) do
1048
    begin
1049
      if indexnow = FSeriesIndex_for_SeriesNr[i]
1050
      then
1051
        FSeriesNr := i;
1052
    end;
1053
 
1054
    result := (FSeriesNr <> -1);
1055
  end;
1056
 
1057
end; //end of CheckForSeriesIndex
1058
 
1059
 
1060
 
1061
 
1062
 
1063
procedure TcollisionTester3DX.AddCollisionObject;
1064
begin
1065
  FSeriesNr := GetSeriesNr(FSeriesIndex);
1066
 
1067
  case Fshape3D of
1068
    box3D      : AddBox;
1069
    sphere3D   : AddSphere;
1070
    cylinder3D : AddCylinder;
1071
    ellipsoid3D: AddEllipsoid;
1072
    Conus3D    : AddConus;
1073
  end;
1074
 
1075
end; //end of AddCollisionObject
1076
 
1077
 
1078
 
1079
 
1080
 
1081
function TCollisionTester3DX.DestroyCollisionObject: boolean;
1082
var
1083
  test_nr : integer;
1084
begin
1085
  //remove all collision objects connected with the 3D-object
1086
  //with the index FnextDestroyNr
1087
 
1088
  //Check whether series index exists
1089
  if CheckForSeriesIndex(FSeriesIndex)
1090
  then
1091
  begin
1092
    //FSeriesNr was found
1093
    test_nr := 0;
1094
 
1095
    while (test_nr <= (Fcoll_nr_objects[FSeriesNr] - 1)) do
1096
    begin
1097
      if Fcoll_objectnr[FSeriesNr, test_nr] = FnextDestroyNr
1098
      then
1099
        remove_collision_object(FSeriesNr, FnextDestroyNr)
1100
      else
1101
        inc(test_nr);
1102
    end; //end of while loop
1103
 
1104
    //now we have to decrement all Fcoll_objectnr values larger than object_nr
1105
    //because the main program does a similar decrementation when the 3D-object
1106
    //is removed
1107
 
1108
    if Fcoll_nr_objects[FSeriesNr] > 0
1109
    then
1110
    begin
1111
      //the series is not empty
1112
      for test_nr := 0 to (Fcoll_nr_objects[FSeriesNr] - 1) do
1113
      begin
1114
        if Fcoll_objectnr[FSeriesNr, test_nr] > FNextDestroyNr
1115
        then
1116
          dec(Fcoll_objectnr[FSeriesNr, test_nr]);
1117
      end;
1118
    end
1119
    else
1120
      destroy_empty_Series(FSeriesNr);
1121
 
1122
 
1123
    result := true; //collision object was destroyed
1124
 
1125
  end //end of CheckForSeriesIndex...
1126
  else
1127
    result := false; //unable to destroy
1128
 
1129
end; //end of DestroyCollisionObject
1130
 
1131
 
1132
 
1133
 
1134
 
1135
 
1136
function TcollisionTester3DX.coll_test_sphere(coll_nr : byte;
1137
                              old_attacker_position, attacker_position : TD3DVector;
1138
                              bullet_radius : TD3DValue; longshot : boolean): boolean;
1139
var
1140
  new_eye, old_eye : TD3DVector;
1141
  dstep, step, center : TD3DVector;
1142
  radius, d0, d1, d2, rod, rod2, t1, t2 : TD3DValue;
1143
begin
1144
  result := false;
1145
 
1146
  //Get the coordinates of the old eye_position in the actual coll frame
1147
  FFrameSeries[FSeriesIndex, FNrinFrameSeries[FSeriesNr, coll_nr]].InverseTransform
1148
                 (old_eye, old_attacker_position);
1149
 
1150
  //Get the coordinates of the eye_position in the actual coll frame
1151
  FFrameSeries[FSeriesIndex, FNrinFrameSeries[FSeriesNr, coll_nr]].InverseTransform
1152
                 (new_eye, attacker_position);
1153
 
1154
  center.x := (Fcoll_box_max[FSeriesNr, coll_nr].x
1155
             + Fcoll_box_min[FSeriesNr, coll_nr].x)/2;
1156
  center.y := (Fcoll_box_max[FSeriesNr, coll_nr].y
1157
             + Fcoll_box_min[FSeriesNr, coll_nr].y)/2;
1158
  center.z := (Fcoll_box_max[FSeriesNr, coll_nr].z
1159
             + Fcoll_box_min[FSeriesNr, coll_nr].z)/2;
1160
 
1161
  //radius of sphere enlarged with the radius of the bullet
1162
  //to cover the space where a collision may occure
1163
  radius := Fcoll_radius[FSeriesNr, coll_nr] + bullet_radius;
1164
 
1165
  //eye to center distance
1166
  dstep.x := old_eye.x - center.x;
1167
  dstep.y := old_eye.y - center.y;
1168
  dstep.z := old_eye.z - center.z;
1169
 
1170
  //step in eye position
1171
  step.x := new_eye.x - old_eye.x;
1172
  step.y := new_eye.y - old_eye.y;
1173
  step.z := new_eye.z - old_eye.z;
1174
 
1175
  //collision is only possible when something moves
1176
  if (abs(step.x) < 1e-3) and (abs(step.y) < 1e-3) and (abs(step.z) < 1e-3)
1177
  then
1178
  begin
1179
    result := false;
1180
    exit;
1181
  end;
1182
 
1183
 
1184
  //factors
1185
  d0 := sqr(dstep.x) + sqr(dstep.y) + sqr(dstep.z) - sqr(radius);
1186
  d1 := 2 * (step.x * dstep.x + step.y * dstep.y + step.z * dstep.z);
1187
  d2 := sqr(step.x) + sqr(step.y) + sqr(step.z);
1188
 
1189
  //solving an equation of the second degree
1190
  rod := sqr(d1) - 4 * d2 * d0;
1191
 
1192
  //d2 is never zero
1193
  if rod > 0
1194
  then
1195
  begin
1196
    rod2 := sqrt(rod);
1197
    t1 := (-d1 - rod2)/2/d2;
1198
    t2 := (-d1 + rod2)/2/d2;
1199
 
1200
    // if longshot then look into all future
1201
    if longshot
1202
    then
1203
      result := (t1 >= 0) or (t2 >= 0)
1204
    else
1205
    begin
1206
      //collision in between the starting and the ending point if
1207
      result := ((t1 >= 0) and (t1 <= 1))
1208
             or ((t2 >= 0) and (t2 <= 1));
1209
    end;
1210
  end;
1211
 
1212
end; //end of coll_test_sphere
1213
 
1214
 
1215
 
1216
 
1217
function TcollisionTester3DX.coll_test_ellipsoid(coll_nr : byte;
1218
                              old_attacker_position, attacker_position : TD3DVector;
1219
                              bullet_radius : TD3DValue; longshot : boolean): boolean;
1220
var
1221
  new_eye, old_eye : TD3DVector;
1222
  dstep, step, center : TD3DVector;
1223
  d0, d1, d2, rod, rod2, t1, t2, a, b, c : TD3DValue;
1224
begin
1225
  result := false;
1226
 
1227
  //Get the coordinates of the old eye_position in the actual coll frame
1228
  FFrameSeries[FSeriesIndex, FNrinFrameSeries[FSeriesNr, coll_nr]].InverseTransform
1229
                 (old_eye, old_attacker_position);
1230
 
1231
  //Get the coordinates of the eye_position in the actual coll frame
1232
  FFrameSeries[FSeriesIndex, FNrinFrameSeries[FSeriesNr, coll_nr]].InverseTransform
1233
                 (new_eye, attacker_position);
1234
 
1235
  center.x := (Fcoll_box_max[FSeriesNr, coll_nr].x
1236
             + Fcoll_box_min[FSeriesNr, coll_nr].x)/2;
1237
  center.y := (Fcoll_box_max[FSeriesNr, coll_nr].y
1238
             + Fcoll_box_min[FSeriesNr, coll_nr].y)/2;
1239
  center.z := (Fcoll_box_max[FSeriesNr, coll_nr].z
1240
             + Fcoll_box_min[FSeriesNr, coll_nr].z)/2;
1241
 
1242
  //x, y and z radius of ellipsoid enlarged with the radius of the bullet
1243
  //to cover the space where a collision may occure
1244
  a := (Fcoll_box_max[FSeriesNr, coll_nr].x
1245
             - Fcoll_box_min[FSeriesNr, coll_nr].x)/2 + bullet_radius;
1246
  b := (Fcoll_box_max[FSeriesNr, coll_nr].y
1247
             - Fcoll_box_min[FSeriesNr, coll_nr].y)/2 + bullet_radius;
1248
  c := (Fcoll_box_max[FSeriesNr, coll_nr].z
1249
             - Fcoll_box_min[FSeriesNr, coll_nr].z)/2 + bullet_radius;
1250
 
1251
  //eye to center distance
1252
  dstep.x := old_eye.x - center.x;
1253
  dstep.y := old_eye.y - center.y;
1254
  dstep.z := old_eye.z - center.z;
1255
 
1256
  //step in eye position
1257
  step.x := new_eye.x - old_eye.x;
1258
  step.y := new_eye.y - old_eye.y;
1259
  step.z := new_eye.z - old_eye.z;
1260
 
1261
  //collision is only possible when something moves
1262
  if (abs(step.x) < 1e-3) and (abs(step.y) < 1e-3) and (abs(step.z) < 1e-3)
1263
  then
1264
  begin
1265
    result := false;
1266
    exit;
1267
  end;
1268
 
1269
 
1270
  //factors
1271
  d0 := sqr(b * c * dstep.x) + sqr(a * c * dstep.y) + sqr(a * b * dstep.z)
1272
        - sqr(a * b * c);
1273
  d1 := 2 * (sqr(b * c) * step.x * dstep.x + sqr(a * c) * step.y * dstep.y
1274
        + sqr(a * b) * step.z * dstep.z);
1275
  d2 := sqr(b * c * step.x) + sqr(a * c * step.y) + sqr(a * b * step.z);
1276
 
1277
  //solving an equation of the second degree
1278
  rod := sqr(d1) - 4 * d2 * d0;
1279
 
1280
  //d2 is never zero
1281
  if rod > 0
1282
  then
1283
  begin
1284
    rod2 := sqrt(rod);
1285
    t1 := (-d1 - rod2)/2/d2;
1286
    t2 := (-d1 + rod2)/2/d2;
1287
 
1288
    // if longshot then look into all future
1289
    if longshot
1290
    then
1291
      result := (t1 >= 0) or (t2 >= 0)
1292
    else
1293
    begin
1294
      //collision in between the starting and the ending point if
1295
      result := ((t1 >= 0) and (t1 <= 1))
1296
             or ((t2 >= 0) and (t2 <= 1));
1297
    end;
1298
  end;
1299
 
1300
end; //end of coll_test_ellipsoid
1301
 
1302
 
1303
 
1304
 
1305
 
1306
function TcollisionTester3DX.coll_test_cylinder(coll_nr : byte;
1307
                              old_attacker_position, attacker_position : TD3DVector;
1308
                              bullet_radius : TD3DValue; longshot : boolean): boolean;
1309
var
1310
  distance : TD3DValue;
1311
  new_eye, old_eye : TD3DVector;
1312
  dstep, step, center : TD3DVector;
1313
  radius, d0, d1, d2, rod, rod2, t1, t2, xc1, yc1, zc1, xc2, yc2, zc2 : TD3DValue;
1314
begin
1315
  result := false;
1316
 
1317
 
1318
  //Get the coordinates of the old eye_position in the actual coll frame
1319
  FFrameSeries[FSeriesIndex, FNrinFrameSeries[FSeriesNr, coll_nr]].InverseTransform
1320
                 (old_eye, old_attacker_position);
1321
 
1322
  //Get the coordinates of the eye_position in the actual coll frame
1323
  FFrameSeries[FSeriesIndex, FNrinFrameSeries[FSeriesNr, coll_nr]].InverseTransform
1324
                 (new_eye, attacker_position);
1325
 
1326
  center.x := (Fcoll_box_max[FSeriesNr, coll_nr].x
1327
             + Fcoll_box_min[FSeriesNr, coll_nr].x)/2;
1328
  center.y := (Fcoll_box_max[FSeriesNr, coll_nr].y
1329
             + Fcoll_box_min[FSeriesNr, coll_nr].y)/2;
1330
  center.z := (Fcoll_box_max[FSeriesNr, coll_nr].z
1331
             + Fcoll_box_min[FSeriesNr, coll_nr].z)/2;
1332
 
1333
  //radius of sphere enlarged with the radius of the bullet
1334
  //to cover the space where a collision may occure
1335
  radius := Fcoll_radius[FSeriesNr, coll_nr] + bullet_radius;
1336
 
1337
  //eye to center distance
1338
  dstep.x := old_eye.x - center.x;
1339
  dstep.y := old_eye.y - center.y;
1340
  dstep.z := old_eye.z - center.z;
1341
 
1342
  //step in eye position
1343
  step.x := new_eye.x - old_eye.x;
1344
  step.y := new_eye.y - old_eye.y;
1345
  step.z := new_eye.z - old_eye.z;
1346
 
1347
  //collision is only possible when something moves
1348
  if (abs(step.x) < 1e-3) and (abs(step.y) < 1e-3) and (abs(step.z) < 1e-3)
1349
  then
1350
  begin
1351
    result := false;
1352
    exit;
1353
  end;
1354
 
1355
  d0 := 1; //just to avoid warnings
1356
  d1 := 1;
1357
  d2 := 1;
1358
 
1359
 
1360
  //The cylinder is alined parallel to the x, y or z axis
1361
  case FOrientation3D of
1362
  symmetric_x :
1363
  begin
1364
    //factors
1365
    d0 := sqr(dstep.y) + sqr(dstep.z) - sqr(radius);
1366
    d1 := 2 * (step.y * dstep.y + step.z * dstep.z);
1367
    d2 := sqr(step.y) + sqr(step.z);
1368
  end;
1369
  symmetric_y :
1370
  begin
1371
    //factors
1372
    d0 := sqr(dstep.x) + sqr(dstep.z) - sqr(radius);
1373
    d1 := 2 * (step.x * dstep.x + step.z * dstep.z);
1374
    d2 := sqr(step.x) + sqr(step.z);
1375
  end;
1376
  symmetric_z :
1377
  begin
1378
    //factors
1379
    d0 := sqr(dstep.x) + sqr(dstep.y) - sqr(radius);
1380
    d1 := 2 * (step.x * dstep.x + step.y * dstep.y);
1381
    d2 := sqr(step.x) + sqr(step.y);
1382
  end;
1383
  end; //end of case FOrientation3D of
1384
 
1385
 
1386
  //solving an equation of the second degree
1387
  rod := sqr(d1) - 4 * d2 * d0;
1388
 
1389
  //d2 is never zero
1390
  if rod >= 0
1391
  then
1392
  begin
1393
    //only then is the collision possible
1394
    rod2 := sqrt(rod);
1395
    t1 := (-d1 - rod2)/2/d2;
1396
    t2 := (-d1 + rod2)/2/d2;
1397
 
1398
    // if longshot then look into all future
1399
    if longshot
1400
    then
1401
      result := (t1 >= 0) or (t2 >= 0)
1402
    else
1403
    begin
1404
      //collision in between the starting and the ending point if
1405
      result := ((t1 >= 0) and (t1 <= 1))
1406
             or ((t2 >= 0) and (t2 <= 1));
1407
    end;
1408
 
1409
    // however the collision also affords that we are within the length of the cylinder
1410
    if result then
1411
    begin
1412
      case FOrientation3D of
1413
      symmetric_x :
1414
      begin
1415
        xc1 := old_eye.x + t1 * step.x;
1416
        xc2 := old_eye.x + t2 * step.x;
1417
 
1418
 
1419
        if longshot
1420
        then
1421
          result :=
1422
           (result and (t1 >= 0) and
1423
           (xc1 >= (Fcoll_box_min[FseriesNr, coll_nr].x - bullet_radius)) and
1424
           (xc1 <= (Fcoll_box_max[FseriesNr, coll_nr].x + bullet_radius)) )
1425
          or
1426
           (result and (t2 >= 0) and
1427
           (xc2 >= (Fcoll_box_min[FseriesNr, coll_nr].x - bullet_radius)) and
1428
           (xc2 <= (Fcoll_box_max[FseriesNr, coll_nr].x + bullet_radius)) )
1429
        else
1430
          result :=
1431
           (result and (t1 >= 0) and (t1 <= 1) and
1432
           (xc1 >= (Fcoll_box_min[FseriesNr, coll_nr].x - bullet_radius)) and
1433
           (xc1 <= (Fcoll_box_max[FseriesNr, coll_nr].x + bullet_radius)) )
1434
         or
1435
           (result and (t2 >= 0) and (t2 <= 1) and
1436
           (xc2 >= (Fcoll_box_min[FseriesNr, coll_nr].x - bullet_radius)) and
1437
           (xc2 <= (Fcoll_box_max[FseriesNr, coll_nr].x + bullet_radius)) );
1438
 
1439
         //if collision detected then exit now
1440
         if result then exit;
1441
 
1442
      end;
1443
      symmetric_y :
1444
      begin
1445
        yc1 := old_eye.y + t1 * step.y;
1446
        yc2 := old_eye.y + t2 * step.y;
1447
 
1448
 
1449
        if longshot
1450
        then
1451
          result :=
1452
           (result and (t1 >= 0) and
1453
           (yc1 >= (Fcoll_box_min[FseriesNr, coll_nr].y - bullet_radius)) and
1454
           (yc1 <= (Fcoll_box_max[FseriesNr, coll_nr].y + bullet_radius)) )
1455
          or
1456
           (result and (t2 >= 0) and
1457
           (yc2 >= (Fcoll_box_min[FseriesNr, coll_nr].y - bullet_radius)) and
1458
           (yc2 <= (Fcoll_box_max[FseriesNr, coll_nr].y + bullet_radius)) )
1459
        else
1460
          result :=
1461
           (result and (t1 >= 0) and (t1 <= 1) and
1462
           (yc1 >= (Fcoll_box_min[FseriesNr, coll_nr].y - bullet_radius)) and
1463
           (yc1 <= (Fcoll_box_max[FseriesNr, coll_nr].y + bullet_radius)) )
1464
         or
1465
           (result and (t2 >= 0) and (t2 <= 1) and
1466
           (yc2 >= (Fcoll_box_min[FseriesNr, coll_nr].y - bullet_radius)) and
1467
           (yc2 <= (Fcoll_box_max[FseriesNr, coll_nr].y + bullet_radius)) );
1468
 
1469
         //if collision detected then exit now
1470
         if result then exit;
1471
 
1472
 
1473
      end;
1474
      symmetric_z :
1475
      begin
1476
        zc1 := old_eye.z + t1 * step.z;
1477
        zc2 := old_eye.z + t2 * step.z;
1478
 
1479
 
1480
        if longshot
1481
        then
1482
          result :=
1483
           (result and (t1 >= 0) and
1484
           (zc1 >= (Fcoll_box_min[FseriesNr, coll_nr].z - bullet_radius)) and
1485
           (zc1 <= (Fcoll_box_max[FseriesNr, coll_nr].z + bullet_radius)) )
1486
          or
1487
           (result and (t2 >= 0) and
1488
           (zc2 >= (Fcoll_box_min[FseriesNr, coll_nr].z - bullet_radius)) and
1489
           (zc2 <= (Fcoll_box_max[FseriesNr, coll_nr].z + bullet_radius)) )
1490
        else
1491
          result :=
1492
           (result and (t1 >= 0) and (t1 <= 1) and
1493
           (zc1 >= (Fcoll_box_min[FseriesNr, coll_nr].z - bullet_radius)) and
1494
           (zc1 <= (Fcoll_box_max[FseriesNr, coll_nr].z + bullet_radius)) )
1495
         or
1496
           (result and (t2 >= 0) and (t2 <= 1) and
1497
           (zc2 >= (Fcoll_box_min[FseriesNr, coll_nr].z - bullet_radius)) and
1498
           (zc2 <= (Fcoll_box_max[FseriesNr, coll_nr].z + bullet_radius)) );
1499
 
1500
         //if collision detected then exit now
1501
         if result then exit;
1502
      end;
1503
 
1504
      end; //end of case
1505
    end;
1506
 
1507
    //exit if a collision occured
1508
    if result then exit;
1509
  end;
1510
 
1511
 
1512
  //the collision may also occur with the end surfaces of the cylinder
1513
  case FOrientation3D of
1514
  symmetric_x :
1515
  begin
1516
    if step.x > 1e-6
1517
    then
1518
    begin
1519
      //1st end surface
1520
      t1 := (Fcoll_box_min[FseriesNr, coll_Nr].x - old_eye.x)/step.x;
1521
      yc1 := old_eye.y + t1 * step.y;
1522
      zc1 := old_eye.z + t1 * step.z;
1523
 
1524
      distance := sqrt( sqr(yc1 - center.y) + sqr(zc1 - center.z) );
1525
 
1526
      result := (distance < radius) and (t1 >= 0);
1527
      if not longshot then result := result and (t1 <= 1);
1528
      if result then exit;
1529
 
1530
      //2nd end surface
1531
      t1 := (Fcoll_box_max[FseriesNr, coll_Nr].x - old_eye.x)/step.x;
1532
      yc1 := old_eye.y + t1 * step.y;
1533
      zc1 := old_eye.z + t1 * step.z;
1534
 
1535
      distance := sqrt( sqr(yc1 - center.y) + sqr(zc1 - center.z) );
1536
 
1537
      result := (distance < radius) and (t1 >= 0);
1538
      if not longshot then result := result and (t1 <= 1);
1539
      if result then exit;
1540
    end;
1541
  end;
1542
  symmetric_y :
1543
  begin
1544
    if step.y > 1e-6
1545
    then
1546
    begin
1547
      //1st end surface
1548
      t1 := (Fcoll_box_min[FseriesNr, coll_Nr].y - old_eye.y)/step.y;
1549
      xc1 := old_eye.x + t1 * step.x;
1550
      zc1 := old_eye.z + t1 * step.z;
1551
 
1552
      distance := sqrt( sqr(xc1 - center.x) + sqr(zc1 - center.z) );
1553
 
1554
      result := (distance < radius) and (t1 >= 0);
1555
      if not longshot then result := result and (t1 <= 1);
1556
      if result then exit;
1557
 
1558
      //2nd end surface
1559
      t1 := (Fcoll_box_max[FseriesNr, coll_Nr].y - old_eye.y)/step.y;
1560
      xc1 := old_eye.x + t1 * step.x;
1561
      zc1 := old_eye.z + t1 * step.z;
1562
 
1563
      distance := sqrt( sqr(xc1 - center.x) + sqr(zc1 - center.z) );
1564
 
1565
      result := (distance < radius) and (t1 >= 0);
1566
      if not longshot then result := result and (t1 <= 1);
1567
      if result then exit;
1568
    end;
1569
 
1570
  end;
1571
  symmetric_z :
1572
  begin
1573
    if step.z > 1e-6
1574
    then
1575
    begin
1576
      //1st end surface
1577
      t1 := (Fcoll_box_min[FseriesNr, coll_Nr].z - old_eye.z)/step.z;
1578
      xc1 := old_eye.x + t1 * step.x;
1579
      yc1 := old_eye.y + t1 * step.y;
1580
 
1581
      distance := sqrt( sqr(xc1 - center.x) + sqr(yc1 - center.y) );
1582
 
1583
      result := (distance < radius) and (t1 >= 0);
1584
      if not longshot then result := result and (t1 <= 1);
1585
      if result then exit;
1586
 
1587
      //2nd end surface
1588
      t1 := (Fcoll_box_max[FseriesNr, coll_Nr].z - old_eye.z)/step.z;
1589
      xc1 := old_eye.x + t1 * step.x;
1590
      yc1 := old_eye.y + t1 * step.y;
1591
 
1592
      distance := sqrt( sqr(xc1 - center.x) + sqr(yc1 - center.y) );
1593
 
1594
      result := (distance < radius) and (t1 >= 0);
1595
      if not longshot then result := result and (t1 <= 1);
1596
      if result then exit;
1597
    end;
1598
 
1599
  end;
1600
 
1601
 
1602
  end; //end of case
1603
 
1604
end; //end of coll_test_cylinder
1605
 
1606
 
1607
 
1608
 
1609
 
1610
function TcollisionTester3DX.coll_test_conus(coll_nr : byte;
1611
                              old_attacker_position, attacker_position : TD3DVector;
1612
                              bullet_radius : TD3DValue; longshot : boolean): boolean;
1613
var
1614
  height3D, width3D : TD3DValue;
1615
  distance : TD3DValue;
1616
  new_eye, old_eye : TD3DVector;
1617
  dstep, step, center : TD3DVector;
1618
  radius, d0, d1, d2, rod, rod2, t1, t2, xc1, yc1, zc1, xc2, yc2, zc2 : TD3DValue;
1619
  xc, yc, zc, conusfact : TD3DValue;
1620
begin
1621
  result := false;
1622
 
1623
  //Get the coordinates of the old eye_position in the actual coll frame
1624
  FFrameSeries[FSeriesIndex, FNrinFrameSeries[FSeriesNr, coll_nr]].InverseTransform
1625
                 (old_eye, old_attacker_position);
1626
 
1627
  //Get the coordinates of the eye_position in the actual coll frame
1628
  FFrameSeries[FSeriesIndex, FNrinFrameSeries[FSeriesNr, coll_nr]].InverseTransform
1629
                 (new_eye, attacker_position);
1630
 
1631
  center.x := (Fcoll_box_max[FSeriesNr, coll_nr].x
1632
             + Fcoll_box_min[FSeriesNr, coll_nr].x)/2;
1633
  center.y := (Fcoll_box_max[FSeriesNr, coll_nr].y
1634
             + Fcoll_box_min[FSeriesNr, coll_nr].y)/2;
1635
  center.z := (Fcoll_box_max[FSeriesNr, coll_nr].z
1636
             + Fcoll_box_min[FSeriesNr, coll_nr].z)/2;
1637
 
1638
 
1639
  //step in eye position
1640
  step.x := new_eye.x - old_eye.x;
1641
  step.y := new_eye.y - old_eye.y;
1642
  step.z := new_eye.z - old_eye.z;
1643
 
1644
  //collision is only possible when something moves
1645
  if (abs(step.x) < 1e-3) and (abs(step.y) < 1e-3) and (abs(step.z) < 1e-3)
1646
  then
1647
  begin
1648
    result := false;
1649
    exit;
1650
  end;
1651
 
1652
  //if FPercentLeftatTop is positiv then the conus is largest at the bottom
1653
  xc := center.x;
1654
  yc := center.y;
1655
  zc := center.z;
1656
 
1657
  width3D := 10;  //just to avoid warnings
1658
  height3D := 10;
1659
 
1660
  case FOrientation3D of
1661
  symmetric_x :
1662
  begin
1663
    height3D := Fcoll_box_max[FSeriesNr, coll_nr].x
1664
              - Fcoll_box_min[FSeriesNr, coll_nr].x;
1665
    width3D := (Fcoll_box_max[FSeriesNr, coll_Nr].y
1666
              - Fcoll_box_min[FSeriesNr, coll_nr].y
1667
              + Fcoll_box_max[FSeriesNr, coll_nr].z
1668
              - Fcoll_box_min[FSeriesNr, coll_nr].z)/2;
1669
 
1670
    //the top of the conus is maller than the bottom of it
1671
    if FPercentLeftatTop >= 0
1672
    then
1673
      xc := center.x - height3D/2 + 100 * height3D/(100 - FpercentLeftatTop)
1674
    else
1675
      xc := center.x + height3D/2 - 100 * height3D/(100 + FpercentLeftatTop);
1676
  end; //end of symmetric_x
1677
  symmetric_y :
1678
  begin
1679
    height3D := Fcoll_box_max[FSeriesNr, coll_nr].y
1680
              - Fcoll_box_min[FSeriesNr, coll_nr].y;
1681
    width3D := (Fcoll_box_max[FSeriesNr, coll_Nr].x
1682
              - Fcoll_box_min[FSeriesNr, coll_nr].x
1683
              + Fcoll_box_max[FSeriesNr, coll_nr].z
1684
              - Fcoll_box_min[FSeriesNr, coll_nr].z)/2;
1685
 
1686
    //the top of the conus is maller than the bottom of it
1687
    if FPercentLeftatTop >= 0
1688
    then
1689
      yc := center.y - height3D/2 + 100 * height3D/(100 - FpercentLeftatTop)
1690
    else
1691
      yc := center.y + height3D/2 - 100 * height3D/(100 + FpercentLeftatTop);
1692
  end; //end of symmetric_y
1693
  symmetric_z :
1694
  begin
1695
    height3D := Fcoll_box_max[FSeriesNr, coll_nr].z
1696
              - Fcoll_box_min[FSeriesNr, coll_nr].z;
1697
    width3D := (Fcoll_box_max[FSeriesNr, coll_Nr].x
1698
              - Fcoll_box_min[FSeriesNr, coll_nr].x
1699
              + Fcoll_box_max[FSeriesNr, coll_nr].y
1700
              - Fcoll_box_min[FSeriesNr, coll_nr].y)/2;
1701
 
1702
    //the top of the conus is maller than the bottom of it
1703
    if FPercentLeftatTop >= 0
1704
    then
1705
      zc := center.z - height3D/2 + 100 * height3D/(100 - FpercentLeftatTop)
1706
    else
1707
      zc := center.z + height3D/2 - 100 * height3D/(100 + FpercentLeftatTop);
1708
  end; //end of symmetric_z
1709
  end; //end of case
1710
 
1711
  //mathematically we need the conusfact describing the ratio between the radius of
1712
  //the large end of the conus and the height of the conus
1713
  if width3D > 0
1714
  then
1715
    conusfact := height3D/2/width3D
1716
  else
1717
    conusfact := 1e9;
1718
 
1719
  //eye to the fictive tip of the conus distance
1720
  dstep.x := old_eye.x - xc;
1721
  dstep.y := old_eye.y - yc;
1722
  dstep.z := old_eye.z - zc;
1723
 
1724
  d0 := 1; //just to avoid warnings
1725
  d1 := 1;
1726
  d2 := 1;
1727
 
1728
  //The conus is aligned parallel to the x, y or z axis
1729
  case FOrientation3D of
1730
  symmetric_x :
1731
  begin
1732
    //factors
1733
    d0 := sqr(dstep.y) + sqr(dstep.z) - sqr(dstep.x * conusfact);
1734
    d1 := 2 * (step.y * dstep.y + step.z * dstep.z
1735
          - sqr(conusfact) * step.x * dstep.x);
1736
    d2 := sqr(step.y) + sqr(step.z) - sqr(conusfact * step.x);
1737
  end;
1738
  symmetric_y :
1739
  begin
1740
    //factors
1741
    d0 := sqr(dstep.x) + sqr(dstep.z) - sqr(dstep.y * conusfact);
1742
    d1 := 2 * (step.x * dstep.x + step.z * dstep.z
1743
          - sqr(conusfact) * step.y * dstep.y);
1744
    d2 := sqr(step.x) + sqr(step.z) - sqr(conusfact * step.y);
1745
  end;
1746
  symmetric_z :
1747
  begin
1748
    //factors
1749
    d0 := sqr(dstep.x) + sqr(dstep.y) - sqr(dstep.z * conusfact);
1750
    d1 := 2 * (step.x * dstep.x + step.y * dstep.y
1751
          - sqr(conusfact) * step.z * dstep.z);
1752
    d2 := sqr(step.x) + sqr(step.y) - sqr(conusfact * step.z);
1753
  end;
1754
  end; //end of case FOrientation3D of
1755
 
1756
 
1757
  //solving an equation of the second degree
1758
  rod := sqr(d1) - 4 * d2 * d0;
1759
 
1760
  //d2 is never zero
1761
  if rod >= 0
1762
  then
1763
  begin
1764
    //only then is the collision possible
1765
    rod2 := sqrt(rod);
1766
    t1 := (-d1 - rod2)/2/d2;
1767
    t2 := (-d1 + rod2)/2/d2;
1768
 
1769
    // if longshot then look into all future
1770
    if longshot
1771
    then
1772
      result := (t1 >= 0) or (t2 >= 0)
1773
    else
1774
    begin
1775
      //collision in between the starting and the ending point if
1776
      result := ((t1 >= 0) and (t1 <= 1))
1777
             or ((t2 >= 0) and (t2 <= 1));
1778
    end;
1779
 
1780
    // however the collision also affords that we are within the length of the conus
1781
    if result then
1782
    begin
1783
      case FOrientation3D of
1784
      symmetric_x :
1785
      begin
1786
        xc1 := old_eye.x + t1 * step.x;
1787
        xc2 := old_eye.x + t2 * step.x;
1788
 
1789
 
1790
        if longshot
1791
        then
1792
          result :=
1793
           (result and (t1 >= 0) and
1794
           (xc1 >= (Fcoll_box_min[FseriesNr, coll_nr].x - bullet_radius)) and
1795
           (xc1 <= (Fcoll_box_max[FseriesNr, coll_nr].x + bullet_radius)) )
1796
          or
1797
           (result and (t2 >= 0) and
1798
           (xc2 >= (Fcoll_box_min[FseriesNr, coll_nr].x - bullet_radius)) and
1799
           (xc2 <= (Fcoll_box_max[FseriesNr, coll_nr].x + bullet_radius)) )
1800
        else
1801
          result :=
1802
           (result and (t1 >= 0) and (t1 <= 1) and
1803
           (xc1 >= (Fcoll_box_min[FseriesNr, coll_nr].x - bullet_radius)) and
1804
           (xc1 <= (Fcoll_box_max[FseriesNr, coll_nr].x + bullet_radius)) )
1805
         or
1806
           (result and (t2 >= 0) and (t2 <= 1) and
1807
           (xc2 >= (Fcoll_box_min[FseriesNr, coll_nr].x - bullet_radius)) and
1808
           (xc2 <= (Fcoll_box_max[FseriesNr, coll_nr].x + bullet_radius)) );
1809
 
1810
         //if collision detected then exit now
1811
         if result then exit;
1812
 
1813
      end;
1814
      symmetric_y :
1815
      begin
1816
        yc1 := old_eye.y + t1 * step.y;
1817
        yc2 := old_eye.y + t2 * step.y;
1818
 
1819
 
1820
        if longshot
1821
        then
1822
          result :=
1823
           (result and (t1 >= 0) and
1824
           (yc1 >= (Fcoll_box_min[FseriesNr, coll_nr].y - bullet_radius)) and
1825
           (yc1 <= (Fcoll_box_max[FseriesNr, coll_nr].y + bullet_radius)) )
1826
          or
1827
           (result and (t2 >= 0) and
1828
           (yc2 >= (Fcoll_box_min[FseriesNr, coll_nr].y - bullet_radius)) and
1829
           (yc2 <= (Fcoll_box_max[FseriesNr, coll_nr].y + bullet_radius)) )
1830
        else
1831
          result :=
1832
           (result and (t1 >= 0) and (t1 <= 1) and
1833
           (yc1 >= (Fcoll_box_min[FseriesNr, coll_nr].y - bullet_radius)) and
1834
           (yc1 <= (Fcoll_box_max[FseriesNr, coll_nr].y + bullet_radius)) )
1835
         or
1836
           (result and (t2 >= 0) and (t2 <= 1) and
1837
           (yc2 >= (Fcoll_box_min[FseriesNr, coll_nr].y - bullet_radius)) and
1838
           (yc2 <= (Fcoll_box_max[FseriesNr, coll_nr].y + bullet_radius)) );
1839
 
1840
         //if collision detected then exit now
1841
         if result then exit;
1842
 
1843
 
1844
      end;
1845
      symmetric_z :
1846
      begin
1847
        zc1 := old_eye.z + t1 * step.z;
1848
        zc2 := old_eye.z + t2 * step.z;
1849
 
1850
 
1851
        if longshot
1852
        then
1853
          result :=
1854
           (result and (t1 >= 0) and
1855
           (zc1 >= (Fcoll_box_min[FseriesNr, coll_nr].z - bullet_radius)) and
1856
           (zc1 <= (Fcoll_box_max[FseriesNr, coll_nr].z + bullet_radius)) )
1857
          or
1858
           (result and (t2 >= 0) and
1859
           (zc2 >= (Fcoll_box_min[FseriesNr, coll_nr].z - bullet_radius)) and
1860
           (zc2 <= (Fcoll_box_max[FseriesNr, coll_nr].z + bullet_radius)) )
1861
        else
1862
          result :=
1863
           (result and (t1 >= 0) and (t1 <= 1) and
1864
           (zc1 >= (Fcoll_box_min[FseriesNr, coll_nr].z - bullet_radius)) and
1865
           (zc1 <= (Fcoll_box_max[FseriesNr, coll_nr].z + bullet_radius)) )
1866
         or
1867
           (result and (t2 >= 0) and (t2 <= 1) and
1868
           (zc2 >= (Fcoll_box_min[FseriesNr, coll_nr].z - bullet_radius)) and
1869
           (zc2 <= (Fcoll_box_max[FseriesNr, coll_nr].z + bullet_radius)) );
1870
 
1871
         //if collision detected then exit now
1872
         if result then exit;
1873
      end;
1874
 
1875
      end; //end of case
1876
    end;
1877
 
1878
    //exit if a collision occured
1879
    if result then exit;
1880
  end;
1881
 
1882
 
1883
  //the collision may also occur with the end surfaces of the cylinder
1884
  case FOrientation3D of
1885
  symmetric_x :
1886
  begin
1887
    if step.x > 1e-6
1888
    then
1889
    begin
1890
      //1st end surface
1891
      t1 := (Fcoll_box_min[FseriesNr, coll_Nr].x - old_eye.x)/step.x;
1892
      yc1 := old_eye.y + t1 * step.y;
1893
      zc1 := old_eye.z + t1 * step.z;
1894
 
1895
      distance := sqrt( sqr(yc1 - center.y) + sqr(zc1 - center.z) );
1896
 
1897
      if FPercentLeftatTop >= 0
1898
      then
1899
        radius := width3D/2 //the large end of the conus is down
1900
      else
1901
        radius := -width3D/2 * FPercentLeftatTop;
1902
 
1903
      radius := radius + bullet_radius;
1904
 
1905
      result := (distance < radius) and (t1 >= 0);
1906
      if not longshot then result := result and (t1 <= 1);
1907
      if result then exit;
1908
 
1909
      //2nd end surface
1910
      t1 := (Fcoll_box_max[FseriesNr, coll_Nr].x - old_eye.x)/step.x;
1911
      yc1 := old_eye.y + t1 * step.y;
1912
      zc1 := old_eye.z + t1 * step.z;
1913
 
1914
      distance := sqrt( sqr(yc1 - center.y) + sqr(zc1 - center.z) );
1915
 
1916
      if FPercentLeftatTop >= 0
1917
      then
1918
        radius := width3D/2 * FPercentLeftatTop //the small end of the conus is upwards
1919
      else
1920
        radius := width3D/2;
1921
 
1922
      radius := radius + bullet_radius;
1923
 
1924
      result := (distance < radius) and (t1 >= 0);
1925
      if not longshot then result := result and (t1 <= 1);
1926
      if result then exit;
1927
    end;
1928
  end;
1929
  symmetric_y :
1930
  begin
1931
    if step.y > 1e-6
1932
    then
1933
    begin
1934
      //1st end surface
1935
      t1 := (Fcoll_box_min[FseriesNr, coll_Nr].y - old_eye.y)/step.y;
1936
      xc1 := old_eye.x + t1 * step.x;
1937
      zc1 := old_eye.z + t1 * step.z;
1938
 
1939
      distance := sqrt( sqr(xc1 - center.x) + sqr(zc1 - center.z) );
1940
 
1941
      if FPercentLeftatTop >= 0
1942
      then
1943
        radius := width3D/2 //the large end of the conus is down
1944
      else
1945
        radius := -width3D/2 * FPercentLeftatTop;
1946
 
1947
      radius := radius + bullet_radius;
1948
 
1949
      result := (distance < radius) and (t1 >= 0);
1950
      if not longshot then result := result and (t1 <= 1);
1951
      if result then exit;
1952
 
1953
      //2nd end surface
1954
      t1 := (Fcoll_box_max[FseriesNr, coll_Nr].y - old_eye.y)/step.y;
1955
      xc1 := old_eye.x + t1 * step.x;
1956
      zc1 := old_eye.z + t1 * step.z;
1957
 
1958
      distance := sqrt( sqr(xc1 - center.x) + sqr(zc1 - center.z) );
1959
 
1960
      if FPercentLeftatTop >= 0
1961
      then
1962
        radius := width3D/2 * FPercentLeftatTop //the small end of the conus is upwards
1963
      else
1964
        radius := width3D/2;
1965
 
1966
      radius := radius + bullet_radius;
1967
 
1968
      result := (distance < radius) and (t1 >= 0);
1969
      if not longshot then result := result and (t1 <= 1);
1970
      if result then exit;
1971
    end;
1972
 
1973
  end;
1974
  symmetric_z :
1975
  begin
1976
    if step.z > 1e-6
1977
    then
1978
    begin
1979
      //1st end surface
1980
      t1 := (Fcoll_box_min[FseriesNr, coll_Nr].z - old_eye.z)/step.z;
1981
      xc1 := old_eye.x + t1 * step.x;
1982
      yc1 := old_eye.y + t1 * step.y;
1983
 
1984
      distance := sqrt( sqr(xc1 - center.x) + sqr(yc1 - center.y) );
1985
 
1986
      if FPercentLeftatTop >= 0
1987
      then
1988
        radius := width3D/2 //the large end of the conus is down
1989
      else
1990
        radius := width3D/2 * FPercentLeftatTop;
1991
 
1992
      radius := radius + bullet_radius;
1993
 
1994
      result := (distance < radius) and (t1 >= 0);
1995
      if not longshot then result := result and (t1 <= 1);
1996
      if result then exit;
1997
 
1998
      //2nd end surface
1999
      t1 := (Fcoll_box_max[FseriesNr, coll_Nr].z - old_eye.z)/step.z;
2000
      xc1 := old_eye.x + t1 * step.x;
2001
      yc1 := old_eye.y + t1 * step.y;
2002
 
2003
      distance := sqrt( sqr(xc1 - center.x) + sqr(yc1 - center.y) );
2004
 
2005
      if FPercentLeftatTop >= 0
2006
      then
2007
        radius := -width3D/2 * FPercentLeftatTop //the small end of the conus is upwards
2008
      else
2009
        radius := width3D/2;
2010
 
2011
      radius := radius + bullet_radius;
2012
 
2013
      result := (distance < radius) and (t1 >= 0);
2014
      if not longshot then result := result and (t1 <= 1);
2015
      if result then exit;
2016
    end;
2017
 
2018
  end;
2019
 
2020
 
2021
  end; //end of case
2022
 
2023
 
2024
end; //end of coll_test_conus
2025
 
2026
 
2027
 
2028
 
2029
function TcollisionTester3DX.coll_test_box(coll_nr : byte;
2030
                              old_attacker_position, attacker_position : TD3DVector;
2031
                              bullet_radius : TD3DValue; longshot : boolean): boolean;
2032
var
2033
  new_eye, old_eye : TD3DVector;
2034
  step : TD3DVector;
2035
  t1, xc, yc, zc : TD3DValue;
2036
begin
2037
  result := false;
2038
 
2039
  //Get the coordinates of the old eye_position in the actual coll frame
2040
  FFrameSeries[FSeriesIndex, FNrinFrameSeries[FSeriesNr, coll_nr]].InverseTransform
2041
                 (old_eye, old_attacker_position);
2042
 
2043
  //Get the coordinates of the eye_position in the actual coll frame
2044
  FFrameSeries[FSeriesIndex, FNrinFrameSeries[FSeriesNr, coll_nr]].InverseTransform
2045
                 (new_eye, attacker_position);
2046
 
2047
  //step in eye position
2048
  step.x := new_eye.x - old_eye.x;
2049
  step.y := new_eye.y - old_eye.y;
2050
  step.z := new_eye.z - old_eye.z;
2051
 
2052
  //collision is only possible when something moves
2053
  if (abs(step.x) < 1e-3) and (abs(step.y) < 1e-3) and (abs(step.z) < 1e-3)
2054
  then
2055
  begin
2056
    result := false;
2057
    exit;
2058
  end;
2059
 
2060
  //check the surfaces which are normal to the x-axis
2061
  if abs(step.x) >= 1E-6
2062
  then
2063
  begin
2064
    //test 1st surface
2065
    t1 := (Fcoll_box_min[FseriesNr, coll_nr].x - old_eye.x)/step.x;
2066
    //collision point
2067
    zc := old_eye.z + t1 * step.z;
2068
    yc := old_eye.y + t1 * step.y;
2069
 
2070
    //collision if the collision point is close enough to the surface
2071
    result :=
2072
      (zc >= (Fcoll_box_min[FseriesNr, coll_nr].z - bullet_radius)) and
2073
      (zc <= (Fcoll_box_max[FseriesNr, coll_nr].z + bullet_radius)) and
2074
      (yc >= (Fcoll_box_min[FseriesNr, coll_nr].y - bullet_radius)) and
2075
      (yc <= (Fcoll_box_max[FseriesNr, coll_nr].y + bullet_radius));
2076
 
2077
    if longshot
2078
    then result := result and (t1 >= 0)
2079
    else result := result and (t1 >= 0) and (t1 <= 1);
2080
 
2081
    //if collision detected then exit now
2082
    if result then exit;
2083
 
2084
    //test 2nd surface
2085
    t1 := (Fcoll_box_max[FseriesNr, coll_nr].x - old_eye.x)/step.x;
2086
    //collision point
2087
    zc := old_eye.z + t1 * step.z;
2088
    yc := old_eye.y + t1 * step.y;
2089
 
2090
    //collision if the collision point is close enough to the surface
2091
    result :=
2092
      (zc >= (Fcoll_box_min[FseriesNr, coll_nr].z - bullet_radius)) and
2093
      (zc <= (Fcoll_box_max[FseriesNr, coll_nr].z + bullet_radius)) and
2094
      (yc >= (Fcoll_box_min[FseriesNr, coll_nr].y - bullet_radius)) and
2095
      (yc <= (Fcoll_box_max[FseriesNr, coll_nr].y + bullet_radius));
2096
 
2097
    if longshot
2098
    then result := result and (t1 >= 0)
2099
    else result := result and (t1 >= 0) and (t1 <= 1);
2100
 
2101
    //if collision detected then exit now
2102
    if result then exit;
2103
 
2104
  end; //end of step.x <> 0
2105
 
2106
 
2107
  //check the surfaces which are normal to the y-axis
2108
  if abs(step.y) >= 1E-6
2109
  then
2110
  begin
2111
    //test 1st surface
2112
    t1 := (Fcoll_box_min[FseriesNr, coll_nr].y - old_eye.y)/step.y;
2113
    //collision point
2114
    xc := old_eye.x + t1 * step.x;
2115
    zc := old_eye.z + t1 * step.z;
2116
 
2117
    //collision if the collision point is close enough to the surface
2118
    result :=
2119
      (xc >= (Fcoll_box_min[FseriesNr, coll_nr].x - bullet_radius)) and
2120
      (xc <= (Fcoll_box_max[FseriesNr, coll_nr].x + bullet_radius)) and
2121
      (zc >= (Fcoll_box_min[FseriesNr, coll_nr].z - bullet_radius)) and
2122
      (zc <= (Fcoll_box_max[FseriesNr, coll_nr].z + bullet_radius));
2123
 
2124
    if longshot
2125
    then result := result and (t1 >= 0)
2126
    else result := result and (t1 >= 0) and (t1 <= 1);
2127
 
2128
    //if collision detected then exit now
2129
    if result then exit;
2130
 
2131
    //test 2nd surface
2132
    t1 := (Fcoll_box_max[FseriesNr, coll_nr].y - old_eye.y)/step.y;
2133
    //collision point
2134
    xc := old_eye.x + t1 * step.x;
2135
    zc := old_eye.z + t1 * step.z;
2136
 
2137
    //collision if the collision point is close enough to the surface
2138
    result :=
2139
      (xc >= (Fcoll_box_min[FseriesNr, coll_nr].x - bullet_radius)) and
2140
      (xc <= (Fcoll_box_max[FseriesNr, coll_nr].x + bullet_radius)) and
2141
      (zc >= (Fcoll_box_min[FseriesNr, coll_nr].z - bullet_radius)) and
2142
      (zc <= (Fcoll_box_max[FseriesNr, coll_nr].z + bullet_radius));
2143
 
2144
    if longshot
2145
    then result := result and (t1 >= 0)
2146
    else result := result and (t1 >= 0) and (t1 <= 1);
2147
 
2148
    //if collision detected then exit now
2149
    if result then exit;
2150
 
2151
  end; //end of step.y <> 0
2152
 
2153
 
2154
 
2155
  //check the surfaces which are normal to the z-axis
2156
  if abs(step.z) >= 1E-6
2157
  then
2158
  begin
2159
    //test 1st surface
2160
    t1 := (Fcoll_box_min[FseriesNr, coll_nr].z - old_eye.z)/step.z;
2161
    //collision point
2162
    xc := old_eye.x + t1 * step.x;
2163
    yc := old_eye.y + t1 * step.y;
2164
 
2165
    //collision if the collision point is close enough to the surface
2166
    result :=
2167
      (xc >= (Fcoll_box_min[FseriesNr, coll_nr].x - bullet_radius)) and
2168
      (xc <= (Fcoll_box_max[FseriesNr, coll_nr].x + bullet_radius)) and
2169
      (yc >= (Fcoll_box_min[FseriesNr, coll_nr].y - bullet_radius)) and
2170
      (yc <= (Fcoll_box_max[FseriesNr, coll_nr].y + bullet_radius));
2171
 
2172
    if longshot
2173
    then result := result and (t1 >= 0)
2174
    else result := result and (t1 >= 0) and (t1 <= 1);
2175
 
2176
    //if collision detected then exit now
2177
    if result then exit;
2178
 
2179
    //test 2nd surface
2180
    t1 := (Fcoll_box_max[FseriesNr, coll_nr].z - old_eye.z)/step.z;
2181
    //collision point
2182
    xc := old_eye.x + t1 * step.x;
2183
    yc := old_eye.y + t1 * step.y;
2184
 
2185
    //collision if the collision point is close enough to the surface
2186
    result :=
2187
      (xc >= (Fcoll_box_min[FseriesNr, coll_nr].x - bullet_radius)) and
2188
      (xc <= (Fcoll_box_max[FseriesNr, coll_nr].x + bullet_radius)) and
2189
      (yc >= (Fcoll_box_min[FseriesNr, coll_nr].y - bullet_radius)) and
2190
      (yc <= (Fcoll_box_max[FseriesNr, coll_nr].y + bullet_radius));
2191
 
2192
    if longshot
2193
    then result := result and (t1 >= 0)
2194
    else result := result and (t1 >= 0) and (t1 <= 1);
2195
 
2196
    //if collision detected then exit now
2197
    if result then exit;
2198
 
2199
  end; //end of step.z <> 0
2200
 
2201
 
2202
end; //end of coll_test_box
2203
 
2204
 
2205
 
2206
 
2207
 
2208
 
2209
function TCollisionTester3DX.BulletDead:boolean;
2210
var
2211
  camera_position, bullet_position : TD3DVector;
2212
  Distance : TD3DValue;
2213
begin
2214
  FBulletFrame.GetPosition(FDXDrawUsed.Scene, bullet_position);
2215
  FDXDrawUsed.Camera.GetPosition(FDXDrawUsed.Scene, camera_position);
2216
 
2217
  Distance := sqr(Bullet_position.x - camera_position.x)
2218
            + sqr(Bullet_position.y - camera_position.y)
2219
            + sqr(Bullet_position.z - camera_position.z);
2220
 
2221
  //remove the bullet if it is beyond the bulletrange or if it is a longshot
2222
  result := (sqrt(Distance) > FBulletRange) or FLongShots;
2223
 
2224
end; //end of BulletDead
2225
 
2226
 
2227
 
2228
 
2229
//use this function to check whether the camera or an object in a distance of
2230
// -from camera- from the camera collides with any collision object
2231
function TCollisionTester3DX.collision: boolean;
2232
var
2233
  i : integer;
2234
  camera_position, camera_direction, camera_up : TD3DVECTOR;
2235
  eye_position : TD3DVector;
2236
begin
2237
  Result := false;
2238
  FBullet_HitlinkNr := -1;
2239
 
2240
  if CheckForSeriesIndex(FSeriesIndex)
2241
  then
2242
  begin
2243
    //The series exists
2244
    if Fcoll_Nr_objects[FSeriesNr] > 0
2245
    then
2246
    begin
2247
      //The series is not empty
2248
 
2249
      //Get the position of the camera
2250
      FDXDrawUsed.Camera.GetPosition(FDXDrawUsed.Scene, camera_position);
2251
      FDXDrawUsed.camera.GetOrientation(FDXDrawUsed.scene, camera_direction, camera_up);
2252
      //calculate the eye position
2253
      eye_position.x := camera_position.x + FFrontDistance * camera_direction.x;
2254
      eye_position.y := camera_position.y + FFrontDistance * camera_direction.y;
2255
      eye_position.z := camera_position.z + FFrontDistance * camera_direction.z;
2256
 
2257
      //test whether the eye collides with any of the collision objects
2258
      i := 0;
2259
      while (not result) and (i < Fcoll_nr_objects[FSeriesNr]) do //0..
2260
      begin
2261
        case Fcoll_shape[FSeriesNr, i] of
2262
          box3D      : Result := coll_test_box(i, FOldEyePosition,
2263
                                 eye_position, FHeadRadius, false);
2264
          sphere3D   : Result := coll_test_sphere(i, FOldEyePosition,
2265
                                 eye_position, FHeadRadius, false);
2266
          cylinder3D : Result := coll_test_cylinder(i, FOldEyePosition,
2267
                                 eye_position, FHeadRadius, false);
2268
          ellipsoid3D: Result := coll_test_ellipsoid(i, FOldEyePosition,
2269
                                 eye_position, FHeadRadius, false);
2270
          conus3D    : Result := coll_test_conus(i, FOldEyePosition,
2271
                                 eye_position, FHeadRadius, false);
2272
        end;
2273
 
2274
        if result then Fbullet_hitLinkNr := Fcoll_objectnr[FseriesNr, i];
2275
        inc(i);
2276
      end;
2277
    end;
2278
  end; //end of if checkforseriesIndex
2279
 
2280
  if result
2281
  then
2282
    ListDataForCollObject;
2283
 
2284
end; //end of collision
2285
 
2286
 
2287
 
2288
 
2289
 
2290
 
2291
 
2292
//use this function to check whether an object sent from the camera collides
2293
//with any collision object
2294
function TCollisionTester3DX.BulletCollision: boolean;
2295
var
2296
  i: integer;
2297
  bullet_position : TD3DVector;
2298
begin
2299
  Result := false;
2300
  FBullet_HitLinkNr := -1;
2301
 
2302
  if checkForSeriesIndex(FSeriesIndex)
2303
  then
2304
  begin
2305
    //Series exists
2306
 
2307
    //test whether eye collides with any of the collision objects
2308
    if Fcoll_Nr_objects[FSeriesNr] > 0
2309
    then
2310
    begin
2311
      //Get position of the bullet
2312
      FBulletFrame.GetPosition(FDXDrawUsed.Scene, bullet_position);
2313
      i := 0;
2314
 
2315
      while (not result) and (i < Fcoll_Nr_objects[FSeriesNr]) do //0..
2316
      begin
2317
        if FColl_Shootable[FseriesNr, i] or
2318
           (FColl_material[FSeriesNr, i] = solid3D)
2319
        then
2320
        begin
2321
          case Fcoll_shape[FSeriesNr, i] of
2322
            box3D      : result := coll_test_box(i, FOldBulletPosition,
2323
                                             bullet_position,
2324
                                             FBulletRadius, FLongShots);
2325
            sphere3D   : result := coll_test_sphere(i, FOldBulletPosition,
2326
                                             bullet_position,
2327
                                             FBulletRadius, FLongShots);
2328
            cylinder3D : result := coll_test_cylinder(i, FOldBulletPosition,
2329
                                             bullet_position,
2330
                                             FBulletRadius, FLongShots);
2331
            ellipsoid3D: result := coll_test_ellipsoid(i, FOldBulletPosition,
2332
                                             bullet_position,
2333
                                             FBulletRadius, FLongShots);
2334
            conus3D    : result := coll_test_conus(i, FOldBulletPosition,
2335
                                             bullet_position,
2336
                                             FBulletRadius, FLongShots);
2337
          end; //end case
2338
        end; //end of if..
2339
 
2340
        if result
2341
        then
2342
          FBullet_HitLinkNr := Fcoll_ObjectNr[FSeriesNr, i];
2343
 
2344
        inc(i);
2345
      end; //end of while
2346
 
2347
      if result
2348
      then
2349
        ListDataForCollObject;
2350
 
2351
    end; //end if Fcoll_Nr_ob....
2352
  end; //end if checkForSeriesIndex...
2353
 
2354
end; //end of bullet_collision
2355
 
2356
 
2357
 
2358
 
2359
procedure TCollisionTester3DX.GetOldBulletPos;
2360
begin
2361
  FbulletFrame.GetPosition(FDXDrawUsed.Scene, FOldBulletPosition);
2362
end; //end of GetOldBulletPos
2363
 
2364
 
2365
procedure TCollisionTester3DX.GetOldEyePos;
2366
var
2367
  OldPos, camera_direction, camera_up : TD3DVector;
2368
begin
2369
  FDXDrawUsed.Camera.GetPosition(FDXDrawUsed.Scene, OldPos);
2370
  FDXDrawUsed.Camera.GetOrientation(FDXDrawUsed.Scene, camera_direction, camera_up);
2371
 
2372
  FOldEyePosition.x := OldPos.x + FFrontDistance * camera_direction.x;
2373
  FOldEyePosition.y := OldPos.y + FFrontDistance * camera_direction.y;
2374
  FOldEyePosition.z := OldPos.z + FFrontDistance * camera_direction.z;
2375
 
2376
end; //end of GetOldEyePos
2377
 
2378
 
2379
 
2380
 
2381
 
2382
 
2383
end.