123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- // *
- // The graphics engine GXScene https://github.com/glscene
- //
- unit GXS.DCEMisc;
- (* Miscelaneous functions used by DCE (Dynamic Collision Engine) *)
- interface
- {$I Stage.Defines.inc}
- uses
- GXS.Coordinates,
- GXS.VectorFileObjects,
- GXS.EllipseCollision,
- Stage.VectorGeometry,
- GXS.VectorLists,
- GXS.Scene,
- GXS.TerrainRenderer,
- GXS.ProxyObjects,
- GXS.MultiProxy,
- Stage.VectorTypes;
- //Calculate and set the collision range
- procedure ECSetCollisionRange(var MovePack: TECMovePack);
- //Set the collider lists to null
- procedure ECResetColliders(var MovePack: TECMovePack);
- //Add freeform's octree data
- procedure ECAddFreeForm(var MovePack: TECMovePack; FreeForm: TgxBaseSceneObject;
- Solid: Boolean; ObjectID: Integer);
- //Add a TriMesh box
- procedure ECAddBox(var MovePack: TECMovePack;
- BoxObj: TgxBaseSceneObject; BoxSize: TAffineVector;
- Solid: Boolean; ObjectID: Integer);
- //Add the terrain as a TriMesh
- procedure ECAddTerrain(var MovePack: TECMovePack;
- TerrainRenderer: TgxTerrainRenderer; Resolution: Single;
- Solid: Boolean; ObjectID: Integer);
- //Add a static ellipsoid
- procedure ECAddEllipsoid(var MovePack: TECMovePack;
- ePos, eRadius: TAffineVector;
- Solid: Boolean; ObjectID: Integer);
- const
- DCEBox: array [0..35] of TAffineVector = (
- (X: 1; Y:-1; Z:-1), (X: 1; Y: 1; Z:-1), (X: 1; Y:-1; Z: 1),
- (X: 1; Y: 1; Z:-1), (X: 1; Y: 1; Z: 1), (X: 1; Y:-1; Z: 1),
- (X: 1; Y: 1; Z:-1), (X:-1; Y: 1; Z:-1), (X:-1; Y: 1; Z: 1),
- (X: 1; Y: 1; Z: 1), (X: 1; Y: 1; Z:-1), (X:-1; Y: 1; Z: 1),
- (X:-1; Y: 1; Z: 1), (X:-1; Y:-1; Z: 1), (X: 1; Y:-1; Z: 1),
- (X: 1; Y: 1; Z: 1), (X:-1; Y: 1; Z: 1), (X: 1; Y:-1; Z: 1),
- (X:-1; Y:-1; Z: 1), (X:-1; Y: 1; Z: 1), (X:-1; Y: 1; Z:-1),
- (X:-1; Y:-1; Z:-1), (X:-1; Y:-1; Z: 1), (X:-1; Y: 1; Z:-1),
- (X: 1; Y:-1; Z: 1), (X:-1; Y:-1; Z: 1), (X: 1; Y:-1; Z:-1),
- (X:-1; Y:-1; Z: 1), (X:-1; Y:-1; Z:-1), (X: 1; Y:-1; Z:-1),
- (X: 1; Y: 1; Z:-1), (X: 1; Y:-1; Z:-1), (X:-1; Y: 1; Z:-1),
- (X: 1; Y:-1; Z:-1), (X:-1; Y:-1; Z:-1), (X:-1; Y: 1; Z:-1)
- );
- implementation //-------------------------------------------------------------
- procedure ECSetCollisionRange(var MovePack: TECMovePack);
- var N: TAffineVector;
- begin
- N.X := Abs(MovePack.Velocity.X) + Abs(MovePack.Gravity.X) + (MovePack.Radius.X);
- N.Y := Abs(MovePack.Velocity.Y) + Abs(MovePack.Gravity.Y) + (MovePack.Radius.Y);
- N.Z := Abs(MovePack.Velocity.Z) + Abs(MovePack.Gravity.Z) + (MovePack.Radius.Z);
- MovePack.CollisionRange := MaxXYZComponent(N);
- end;
- procedure ECResetColliders(var MovePack: TECMovePack);
- begin
- SetLength(MovePack.TriMeshes,0);
- SetLength(MovePack.Freeforms,0);
- SetLength(MovePack.Colliders,0);
- end;
- procedure ECAddFreeForm(var MovePack: TECMovePack; FreeForm: TgxBaseSceneObject;
- Solid: Boolean; ObjectID: Integer);
- var
- i, count : Integer;
- Pos: TVector4f;
- Master: TgxBaseSceneObject;
- d1,d2: Single;
- begin
- Master := FreeForm;
- if Master is TgxFreeFormProxy then
- Master := TgxFreeFormProxy(Master).MasterObject;
- if Master is TgxMultiProxy then
- if TgxMultiProxy(Master).MasterObjects.Count > 0 then
- Master := TgxMultiProxy(Master).MasterObjects[0].MasterObject;
- Assert((Master is TgxFreeForm), 'Object must be freeform, freeformproxy or freeformbased Multiproxy.');
- Assert(Assigned(TgxFreeForm(Master).Octree), 'Octree must have been prepared and setup before use.');
- SetVector(Pos, FreeForm.AbsoluteToLocal(MovePack.Position));
- //Is in boundingsphere?
- d1 := VectorDistance2(MovePack.Position,AffineVectorMake(FreeForm.AbsolutePosition));
- d2 := sqr(MovePack.CollisionRange + Freeform.BoundingSphereRadius);
- if d1 > d2 then exit;
- count := Length(MovePack.Freeforms);
- with TgxFreeForm(Master).Octree do
- begin
- WalkSphereToLeaf(RootNode, Pos, MovePack.CollisionRange);
- if not Assigned(resultarray) then exit;
- //Copy the result array
- SetLength(MovePack.Freeforms,count+1);
- SetLength(MovePack.Freeforms[count].OctreeNodes, Length(resultarray));
- for i := 0 to High(resultarray) do
- MovePack.Freeforms[count].OctreeNodes[i] := resultarray[i];
- //Reference to this octree
- MovePack.Freeforms[count].triangleFiler := @triangleFiler;
- MovePack.Freeforms[count].ObjectInfo.AbsoluteMatrix := Freeform.AbsoluteMatrix;
- MovePack.Freeforms[count].ObjectInfo.Solid := Solid;
- MovePack.Freeforms[count].ObjectInfo.ObjectID := ObjectID;
- MovePack.Freeforms[count].InvertedNormals := TgxFreeForm(Master).NormalsOrientation = mnoInvert;
- end;
- end;
- procedure ECAddBox(var MovePack: TECMovePack;
- BoxObj: TgxBaseSceneObject; BoxSize: TAffineVector;
- Solid: Boolean; ObjectID: Integer);
- var t,count,i : Integer;
- p1, p2, p3: TAffineVector;
- BoxRadius,d1,d2: Single;
- begin
- BoxRadius := MaxXYZComponent(BoxSize)*MaxXYZComponent(BoxObj.Scale.AsAffineVector);
- d1 := VectorDistance2(MovePack.Position,AffineVectorMake(BoxObj.AbsolutePosition));
- d2 := sqr(MovePack.CollisionRange + BoxRadius);
- if d1 > d2 then exit;
- //Add the box to the triangle list
- t := Length(MovePack.TriMeshes);
- SetLength(MovePack.TriMeshes,t+1);
- ScaleVector(BoxSize,0.5);
- count := 0;
- i := 0;
- while i < 36 do
- begin
- count := count + 1;
- SetLength(MovePack.TriMeshes[t].Triangles,count);
- with MovePack.TriMeshes[t] do
- begin
- p1 := DCEBox[i]; ScaleVector(p1,BoxSize); p1 := BoxObj.LocalToAbsolute(p1);
- p2 := DCEBox[i+1]; ScaleVector(p2,BoxSize); p2 := BoxObj.LocalToAbsolute(p2);
- p3 := DCEBox[i+2]; ScaleVector(p3,BoxSize); p3 := BoxObj.LocalToAbsolute(p3);
- i := i + 3;
- SetVector(Triangles[count-1].p1, p1);
- SetVector(Triangles[count-1].p2, p2);
- SetVector(Triangles[count-1].p3, p3);
- ObjectInfo.Solid := Solid;
- ObjectInfo.ObjectID := ObjectID;
- end;
- end;
- end;
- procedure ECAddTerrain(var MovePack: TECMovePack;
- TerrainRenderer: TgxTerrainRenderer; Resolution: Single;
- Solid: Boolean; ObjectID: Integer);
- function intvec(x,z: Single): TAffineVector;
- begin
- result.X := x + MovePack.Position.X;
- result.Y := 0 + MovePack.Position.Y;
- result.Z := z + MovePack.Position.Z;
- end;
- function locabs(x,y,z: Single): TAffineVector;
- begin
- //result := TerrainRenderer.LocalToAbsolute(AffineVectorMake(x,y,z));
- //result := AffineVectorMake(x,y,z);
- result.X := x + MovePack.Position.X;
- result.Y := y + TerrainRenderer.AbsolutePosition.Y;
- result.Z := z + MovePack.Position.Z;
- end;
- var count,t : Integer;
- x,y,z: Single;
- begin
- //Add the terrain to the list
- count := Length(MovePack.TriMeshes);
- SetLength(MovePack.TriMeshes,count+1);
- with MovePack.TriMeshes[count] do
- begin
- ObjectInfo.Solid := Solid;
- ObjectInfo.ObjectID := ObjectID;
- t := 0;
- x := - MovePack.CollisionRange;
- while x < MovePack.CollisionRange do
- begin
- z := - MovePack.CollisionRange;
- while z < MovePack.CollisionRange do
- begin
- //Add 2 triangles
- t := t + 2;
- SetLength(Triangles, t);
- //Tri 1
- y := TerrainRenderer.InterpolatedHeight(intvec(x,z));
- Triangles[t-2].p1 := locabs(x,y,z);
- y := TerrainRenderer.InterpolatedHeight(intvec(x,z+Resolution));
- Triangles[t-2].p2 := locabs(x,y,z+Resolution);
- y := TerrainRenderer.InterpolatedHeight(intvec(x+Resolution,z));
- Triangles[t-2].p3 := locabs(x+Resolution,y,z);
- //Tri 2
- y := TerrainRenderer.InterpolatedHeight(intvec(x+Resolution,z+Resolution));
- Triangles[t-1].p1 := locabs(x+Resolution,y,z+Resolution);
- y := TerrainRenderer.InterpolatedHeight(intvec(x+Resolution,z));
- Triangles[t-1].p2 := locabs(x+Resolution,y,z);
- y := TerrainRenderer.InterpolatedHeight(intvec(x,z+Resolution));
- Triangles[t-1].p3 := locabs(x,y,z+Resolution);
- z := z + Resolution;
- end;
- x := x + Resolution;
- end;
- end;
- end;
- procedure ECAddEllipsoid(var MovePack: TECMovePack; ePos, eRadius: TAffineVector;
- Solid: Boolean; ObjectID: Integer);
- var count : Integer;
- d1, d2, r: single;
- begin
- r := MaxXYZComponent(eRadius);
- d1 := VectorDistance2(MovePack.Position,ePos);
- d2 := sqr(MovePack.CollisionRange + r);
- if d1 > d2 then exit;
- //Add possible collider
- count := Length(MovePack.Colliders);
- SetLength(MovePack.Colliders,count+1);
- with MovePack.Colliders[count] do
- begin
- Position := ePos;
- Radius := eRadius;
- ObjectInfo.Solid := Solid;
- ObjectInfo.ObjectID := ObjectID;
- end;
- end;
- // ---------------------------------------------------------------------------
- end.
|