Subversion Repositories spacemission

Rev

Blame | Last modification | View Log | RSS feed

  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.