├── .gitignore
├── Demo.ContentShim
├── Demo.ContentShim.csproj
├── Properties
│ └── AssemblyInfo.cs
├── bin
│ └── x86
│ │ └── Release
│ │ ├── Demo.ContentShim.dll
│ │ └── Demo.ContentShim.pdb
└── obj
│ └── x86
│ └── Release
│ ├── ContentPipeline-{5057B41F-613F-4C6B-A522-42B15B54F3EF}.xml
│ ├── Demo.ContentShim.csproj.FileListAbsolute.txt
│ ├── Demo.ContentShim.dll
│ ├── Demo.ContentShim.pdb
│ ├── Microsoft.Xna.Framework.RuntimeProfile.txt
│ └── cachefile-{5057B41F-613F-4C6B-A522-42B15B54F3EF}-targetpath.txt
├── Demo
├── AnnotationService.cs
├── Camera.cs
├── Clock.cs
├── DeferredDraw.cs
├── Demo.cs
├── Demo.csproj
├── Draw.cs
├── Extensions.cs
├── IPlugIn.cs
├── PlugIn.cs
├── PlugIns
│ ├── AirCombat
│ │ ├── AirCombatPlugin.cs
│ │ ├── Fighter.cs
│ │ └── Missile.cs
│ ├── Arrival
│ │ └── ArrivalPlugIn.cs
│ ├── Boids
│ │ ├── Boid.cs
│ │ └── BoidsPlugIn.cs
│ ├── Ctf
│ │ ├── CtfBase.cs
│ │ ├── CtfEnemy.cs
│ │ ├── CtfPlugIn.cs
│ │ ├── CtfSeeker.cs
│ │ └── Globals.cs
│ ├── FlowField
│ │ ├── FlowFieldFollower.cs
│ │ └── FlowFieldPlugIn.cs
│ ├── GatewayPathFollowing
│ │ └── GatewayPathFollowingPlugin.cs
│ ├── LowSpeedTurn
│ │ ├── LowSpeedTurn.cs
│ │ └── LowSpeedTurnPlugIn.cs
│ ├── MapDrive
│ │ ├── GCRoute.cs
│ │ ├── MapDrivePlugIn.cs
│ │ ├── MapDriver.cs
│ │ └── TerrainMap.cs
│ ├── MeshPathFollowing
│ │ ├── MeshPathFollowingPlugin.cs
│ │ └── PathWalker.cs
│ ├── MultiplePursuit
│ │ ├── MpBase.cs
│ │ ├── MpPlugIn.cs
│ │ ├── MpPursuer.cs
│ │ └── MpWanderer.cs
│ ├── OneTurning
│ │ ├── OneTurning.cs
│ │ └── OneTurningPlugIn.cs
│ ├── Pedestrian
│ │ ├── Globals.cs
│ │ ├── Pedestrian.cs
│ │ └── PedestrianPlugIn.cs
│ └── Soccer
│ │ ├── AABBox.cs
│ │ ├── Ball.cs
│ │ ├── Globals.cs
│ │ ├── Player.cs
│ │ └── SoccerPlugIn.cs
├── PolylinePathway.cs
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
├── SimpleFlowField.cs
└── Trail.cs
├── License.txt
├── Local.testsettings
├── SharpSteer2.Tests
├── LocalSpaceBasisHelpersTest.cs
├── LocalityQueryProximityDatabaseTest.cs
├── MeshPathTest.cs
├── NullAnnotationTest.cs
├── Properties
│ └── AssemblyInfo.cs
├── SharpSteer2.Tests.csproj
├── SimpleVehicleTest.cs
├── SphericalObstacleTests.cs
├── UtilitiesTest.cs
└── Vector3HelpersTest.cs
├── SharpSteer2.WinDemoContent
├── Fonts
│ └── SegoeUiMono.spritefont
└── SharpSteer2.WinDemoContent.contentproj
├── SharpSteer2.ncrunchsolution
├── SharpSteer2.sln
├── SharpSteer2
├── AssemblyAttributes.cs
├── BaseVehicle.cs
├── Database
│ ├── IProximityDatabase.cs
│ ├── ITokenForProximityDatabase.cs
│ ├── LocalityQueryDatabase.cs
│ └── LocalityQueryProximityDatabase.cs
├── Helpers
│ ├── Colors.cs
│ ├── LocalSpaceBasisHelpers.cs
│ ├── MatrixHelpers.cs
│ ├── PathwayHelpers.cs
│ ├── RandomHelpers.cs
│ ├── Utilities.cs
│ ├── Vector3Helpers.cs
│ └── VehicleHelpers.cs
├── IAnnotationService.cs
├── IFlowField.cs
├── ILocalSpaceBasis.cs
├── IVehicle.cs
├── LocalSpace.cs
├── NullAnnotationService.cs
├── Obstacles
│ ├── IObstacle.cs
│ └── SphericalObstacle.cs
├── Pathway
│ ├── GatewayPathway.cs
│ ├── IPathway.cs
│ ├── PolylinePathway.cs
│ └── TrianglePathway.cs
├── Properties
│ └── AssemblyInfo.cs
├── SharpSteer2.csproj
├── SimpleVehicle.cs
└── SteerLibrary.cs
├── push-all.ps1
└── readme.md
/.gitignore:
--------------------------------------------------------------------------------
1 | *.suo
2 | *.user
3 | *.cachefile
4 | *.xnb
5 | *.sln.docstates
6 | *.cache
7 | *.ncrunchproject
8 | *.ncrunchsolution
9 | *.vsmdi
10 | *.testsettings
11 | SharpSteer2/bin
12 | SharpSteer2/obj
13 | Demo/bin
14 | Demo/obj
15 | SharpSteer2.WinDemoContent/bin
16 | SharpSteer2.WinDemoContent/obj
17 | SharpSteer2.Tests/bin
18 | SharpSteer2.Tests/obj
19 | _Resharper.*
--------------------------------------------------------------------------------
/Demo.ContentShim/Demo.ContentShim.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {0001D035-FE3A-4334-9773-56D4D774A4F9}
5 | {6D335F3A-9D43-41b4-9D22-F6F17C4BE596};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
6 | Debug
7 | x86
8 | Library
9 | Properties
10 | Demo.ContentShim
11 | Demo.ContentShim
12 | v4.0
13 | Client
14 | v4.0
15 | Windows
16 | Reach
17 | c619d010-4536-4408-93da-5cb8cb4fa9af
18 | Library
19 |
20 |
21 | true
22 | full
23 | false
24 | bin\x86\Debug
25 | DEBUG;TRACE;WINDOWS
26 | prompt
27 | 4
28 | true
29 | false
30 | x86
31 | false
32 |
33 |
34 | pdbonly
35 | true
36 | bin\x86\Release
37 | TRACE;WINDOWS
38 | prompt
39 | 4
40 | true
41 | false
42 | x86
43 | true
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | 4.0
55 |
56 |
57 | 4.0
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | {5057B41F-613F-4C6B-A522-42B15B54F3EF}
67 | SharpSteer2.WinDemoContent
68 | Content
69 |
70 |
71 |
72 |
73 |
81 |
--------------------------------------------------------------------------------
/Demo.ContentShim/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Demo.ContentShim")]
9 | [assembly: AssemblyProduct("Demo.ContentShim")]
10 | [assembly: AssemblyDescription("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyCopyright("Copyright © 2015")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type. Only Windows
19 | // assemblies support COM.
20 | [assembly: ComVisible(false)]
21 |
22 | // On Windows, the following GUID is for the ID of the typelib if this
23 | // project is exposed to COM. On other platforms, it unique identifies the
24 | // title storage container when deploying this assembly to the device.
25 | [assembly: Guid("cf1257ce-22a6-48ce-be33-84f517cd27af")]
26 |
27 | // Version information for an assembly consists of the following four values:
28 | //
29 | // Major Version
30 | // Minor Version
31 | // Build Number
32 | // Revision
33 | //
34 | [assembly: AssemblyVersion("1.0.0.0")]
--------------------------------------------------------------------------------
/Demo.ContentShim/bin/x86/Release/Demo.ContentShim.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/martindevans/SharpSteer2/d8138fe95e81b38b62b864e457b23b94d9750199/Demo.ContentShim/bin/x86/Release/Demo.ContentShim.dll
--------------------------------------------------------------------------------
/Demo.ContentShim/bin/x86/Release/Demo.ContentShim.pdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/martindevans/SharpSteer2/d8138fe95e81b38b62b864e457b23b94d9750199/Demo.ContentShim/bin/x86/Release/Demo.ContentShim.pdb
--------------------------------------------------------------------------------
/Demo.ContentShim/obj/x86/Release/ContentPipeline-{5057B41F-613F-4C6B-A522-42B15B54F3EF}.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 | Fonts\SegoeUiMono.spritefont
6 | Fonts\SegoeUiMono
7 | FontDescriptionImporter
8 | FontDescriptionProcessor
9 | None
10 |
11 |
12 |
13 | true
14 |
15 | {5057B41F-613F-4C6B-A522-42B15B54F3EF}
16 | Windows
17 | Reach
18 | Release
19 | true
20 | C:\Users\Martin\Documents\dotnet\SharpSteer2\SharpSteer2.WinDemoContent\
21 | C:\Users\Martin\Documents\dotnet\SharpSteer2\Demo.ContentShim\
22 | C:\Users\Martin\Documents\dotnet\SharpSteer2\Demo.ContentShim\obj\x86\Release\
23 | C:\Users\Martin\Documents\dotnet\SharpSteer2\Demo.ContentShim\bin\x86\Release\Content\
24 |
25 |
26 |
27 | C:\Program Files (x86)\Microsoft XNA\XNA Game Studio\v4.0\References\Windows\x86\Microsoft.Xna.Framework.Content.Pipeline.XImporter.dll
28 | 2011-09-01T16:22:30+01:00
29 |
30 |
31 | C:\Program Files (x86)\Microsoft XNA\XNA Game Studio\v4.0\References\Windows\x86\Microsoft.Xna.Framework.Content.Pipeline.VideoImporters.dll
32 | 2011-09-01T16:22:30+01:00
33 |
34 |
35 | C:\Program Files (x86)\Microsoft XNA\XNA Game Studio\v4.0\References\Windows\x86\Microsoft.Xna.Framework.Content.Pipeline.TextureImporter.dll
36 | 2011-09-01T16:22:30+01:00
37 |
38 |
39 | C:\Program Files (x86)\Microsoft XNA\XNA Game Studio\v4.0\References\Windows\x86\Microsoft.Xna.Framework.Content.Pipeline.FBXImporter.dll
40 | 2011-09-01T16:22:30+01:00
41 |
42 |
43 | C:\Program Files (x86)\Microsoft XNA\XNA Game Studio\v4.0\References\Windows\x86\Microsoft.Xna.Framework.Content.Pipeline.EffectImporter.dll
44 | 2011-09-01T16:22:30+01:00
45 |
46 |
47 | C:\Program Files (x86)\Microsoft XNA\XNA Game Studio\v4.0\References\Windows\x86\Microsoft.Xna.Framework.Content.Pipeline.AudioImporters.dll
48 | 2011-09-01T16:22:30+01:00
49 |
50 |
51 | C:\WINDOWS\Microsoft.Net\assembly\GAC_32\Microsoft.Xna.Framework.Content.Pipeline\v4.0_4.0.0.0__842cf8be1de50553\Microsoft.Xna.Framework.Content.Pipeline.dll
52 | 2015-08-02T14:16:37.6210915+01:00
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/Demo.ContentShim/obj/x86/Release/Demo.ContentShim.csproj.FileListAbsolute.txt:
--------------------------------------------------------------------------------
1 | C:\Users\Martin\Documents\dotnet\SharpSteer2\Demo.ContentShim\bin\x86\Release\Demo.ContentShim.dll
2 | C:\Users\Martin\Documents\dotnet\SharpSteer2\Demo.ContentShim\bin\x86\Release\Demo.ContentShim.pdb
3 | C:\Users\Martin\Documents\dotnet\SharpSteer2\Demo.ContentShim\obj\x86\Release\Demo.ContentShim.csprojResolveAssemblyReference.cache
4 | C:\Users\Martin\Documents\dotnet\SharpSteer2\Demo.ContentShim\obj\x86\Release\Microsoft.Xna.Framework.RuntimeProfile.txt
5 | C:\Users\Martin\Documents\dotnet\SharpSteer2\Demo.ContentShim\obj\x86\Release\Demo.ContentShim.dll
6 | C:\Users\Martin\Documents\dotnet\SharpSteer2\Demo.ContentShim\obj\x86\Release\Demo.ContentShim.pdb
7 | C:\Users\Martin\Documents\dotnet\SharpSteer2\Demo.ContentShim\bin\x86\Release\Content\Fonts\SegoeUiMono.xnb
8 |
--------------------------------------------------------------------------------
/Demo.ContentShim/obj/x86/Release/Demo.ContentShim.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/martindevans/SharpSteer2/d8138fe95e81b38b62b864e457b23b94d9750199/Demo.ContentShim/obj/x86/Release/Demo.ContentShim.dll
--------------------------------------------------------------------------------
/Demo.ContentShim/obj/x86/Release/Demo.ContentShim.pdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/martindevans/SharpSteer2/d8138fe95e81b38b62b864e457b23b94d9750199/Demo.ContentShim/obj/x86/Release/Demo.ContentShim.pdb
--------------------------------------------------------------------------------
/Demo.ContentShim/obj/x86/Release/Microsoft.Xna.Framework.RuntimeProfile.txt:
--------------------------------------------------------------------------------
1 | Windows.v4.0.Reach
2 |
--------------------------------------------------------------------------------
/Demo.ContentShim/obj/x86/Release/cachefile-{5057B41F-613F-4C6B-A522-42B15B54F3EF}-targetpath.txt:
--------------------------------------------------------------------------------
1 | Content\Fonts\SegoeUiMono.xnb
2 |
--------------------------------------------------------------------------------
/Demo/AnnotationService.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // Copyright (C) 2007 Michael Coles
5 | // All rights reserved.
6 | //
7 | // This software is licensed as described in the file license.txt, which
8 | // you should have received as part of this distribution. The terms
9 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
10 |
11 | using Microsoft.Xna.Framework;
12 | using SharpSteer2;
13 | using Vector3 = System.Numerics.Vector3;
14 |
15 | namespace Demo
16 | {
17 | public sealed class Annotation : IAnnotationService
18 | {
19 | bool _isEnabled;
20 |
21 | //HACK: change the IDraw to a IDrawService
22 | public static Drawing Drawer;
23 |
24 | // constructor
25 | public Annotation()
26 | {
27 | _isEnabled = true;
28 | }
29 |
30 | ///
31 | /// Indicates whether annotation is enabled.
32 | ///
33 | public bool IsEnabled
34 | {
35 | get { return _isEnabled; }
36 | set { _isEnabled = value; }
37 | }
38 |
39 | // ------------------------------------------------------------------------
40 | // drawing of lines, circles and (filled) disks to annotate steering
41 | // behaviors. When called during OpenSteerDemo's simulation update phase,
42 | // these functions call a "deferred draw" routine which buffer the
43 | // arguments for use during the redraw phase.
44 | //
45 | // note: "circle" means unfilled
46 | // "disk" means filled
47 | // "XZ" means on a plane parallel to the X and Z axes (perp to Y)
48 | // "3d" means the circle is perpendicular to the given "axis"
49 | // "segments" is the number of line segments used to draw the circle
50 |
51 | // draw an opaque colored line segment between two locations in space
52 | public void Line(Vector3 startPoint, Vector3 endPoint, Vector3 color, float opacity = 1)
53 | {
54 | if (_isEnabled && Drawer != null)
55 | {
56 | Drawer.Line(startPoint, endPoint, new Color(new Microsoft.Xna.Framework.Vector3(color.X, color.Y, color.Z)), opacity);
57 | }
58 | }
59 |
60 | // draw a circle on the XZ plane
61 | public void CircleXZ(float radius, Vector3 center, Vector3 color, int segments)
62 | {
63 | CircleOrDiskXZ(radius, center, color, segments, false);
64 | }
65 |
66 | // draw a disk on the XZ plane
67 | public void DiskXZ(float radius, Vector3 center, Vector3 color, int segments)
68 | {
69 | CircleOrDiskXZ(radius, center, color, segments, true);
70 | }
71 |
72 | // draw a circle perpendicular to the given axis
73 | public void Circle3D(float radius, Vector3 center, Vector3 axis, Vector3 color, int segments)
74 | {
75 | CircleOrDisk3D(radius, center, axis, color, segments, false);
76 | }
77 |
78 | // draw a disk perpendicular to the given axis
79 | public void Disk3D(float radius, Vector3 center, Vector3 axis, Vector3 color, int segments)
80 | {
81 | CircleOrDisk3D(radius, center, axis, color, segments, true);
82 | }
83 |
84 | // ------------------------------------------------------------------------
85 | // support for annotation circles
86 | public void CircleOrDiskXZ(float radius, Vector3 center, Vector3 color, int segments, bool filled)
87 | {
88 | CircleOrDisk(radius, Vector3.Zero, center, color, segments, filled, false);
89 | }
90 |
91 | public void CircleOrDisk3D(float radius, Vector3 center, Vector3 axis, Vector3 color, int segments, bool filled)
92 | {
93 | CircleOrDisk(radius, axis, center, color, segments, filled, true);
94 | }
95 |
96 | public void CircleOrDisk(float radius, Vector3 axis, Vector3 center, Vector3 color, int segments, bool filled, bool in3D)
97 | {
98 | if (_isEnabled && Drawer != null)
99 | {
100 | Drawer.CircleOrDisk(radius, axis, center, new Color(new Microsoft.Xna.Framework.Vector3(color.X, color.Y, color.Z)), segments, filled, in3D);
101 | }
102 | }
103 |
104 | // called when steerToAvoidObstacles decides steering is required
105 | // (default action is to do nothing, layered classes can overload it)
106 | public void AvoidObstacle(float minDistanceToCollision)
107 | {
108 | }
109 |
110 | // called when steerToFollowPath decides steering is required
111 | // (default action is to do nothing, layered classes can overload it)
112 | public void PathFollowing(Vector3 future, Vector3 onPath, Vector3 target, float outside)
113 | {
114 | }
115 |
116 | // called when steerToAvoidCloseNeighbors decides steering is required
117 | // (default action is to do nothing, layered classes can overload it)
118 | public void AvoidCloseNeighbor(IVehicle other, float additionalDistance)
119 | {
120 | }
121 |
122 | // called when steerToAvoidNeighbors decides steering is required
123 | // (default action is to do nothing, layered classes can overload it)
124 | public void AvoidNeighbor(IVehicle threat, float steer, Vector3 ourFuture, Vector3 threatFuture)
125 | {
126 | }
127 |
128 | public void VelocityAcceleration(IVehicle vehicle)
129 | {
130 | VelocityAcceleration(vehicle, 3, 3);
131 | }
132 |
133 | public void VelocityAcceleration(IVehicle vehicle, float maxLength)
134 | {
135 | VelocityAcceleration(vehicle, maxLength, maxLength);
136 | }
137 |
138 | public void VelocityAcceleration(IVehicle vehicle, float maxLengthAcceleration, float maxLengthVelocity)
139 | {
140 | Vector3 vColor = new Vector3(255, 102, 255); // pinkish
141 | Vector3 aColor = new Vector3(102, 102, 255); // bluish
142 |
143 | float aScale = maxLengthAcceleration / vehicle.MaxForce;
144 | float vScale = maxLengthVelocity / vehicle.MaxSpeed;
145 | Vector3 p = vehicle.Position;
146 |
147 | Line(p, p + (vehicle.Velocity * vScale), vColor);
148 | Line(p, p + (vehicle.Acceleration * aScale), aColor);
149 | }
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/Demo/DeferredDraw.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // Copyright (C) 2007 Michael Coles
5 | // All rights reserved.
6 | //
7 | // This software is licensed as described in the file license.txt, which
8 | // you should have received as part of this distribution. The terms
9 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
10 |
11 | using System.Collections.Generic;
12 | using Microsoft.Xna.Framework;
13 | using Vector3 = System.Numerics.Vector3;
14 |
15 | namespace Demo
16 | {
17 | public class DeferredLine
18 | {
19 | static DeferredLine()
20 | {
21 | _deferredLines = new List(SIZE);
22 | }
23 |
24 | public static void AddToBuffer(Vector3 s, Vector3 e, Color c)
25 | {
26 | if (_index >= _deferredLines.Count)
27 | _deferredLines.Add(new DeferredLine());
28 |
29 | _deferredLines[_index]._startPoint = s;
30 | _deferredLines[_index]._endPoint = e;
31 | _deferredLines[_index]._color = c;
32 |
33 | _index++;
34 | }
35 |
36 | public static void DrawAll()
37 | {
38 | // draw all lines in the buffer
39 | for (int i = 0; i < _index; i++)
40 | {
41 | DeferredLine dl = _deferredLines[i];
42 | Drawing.iDrawLine(dl._startPoint, dl._endPoint, dl._color);
43 | }
44 |
45 | // reset buffer index
46 | _index = 0;
47 | }
48 |
49 | Vector3 _startPoint;
50 | Vector3 _endPoint;
51 | Color _color;
52 |
53 | static int _index = 0;
54 | const int SIZE = 1000;
55 | static readonly List _deferredLines;
56 | }
57 |
58 | public class DeferredCircle
59 | {
60 | static DeferredCircle()
61 | {
62 | _deferredCircleArray = new DeferredCircle[SIZE];
63 | for (int i = 0; i < SIZE; i++)
64 | {
65 | _deferredCircleArray[i] = new DeferredCircle();
66 | }
67 | }
68 |
69 | public static void AddToBuffer(float radius, Vector3 axis, Vector3 center, Color color, int segments, bool filled, bool in3D)
70 | {
71 | if (_index < SIZE)
72 | {
73 | _deferredCircleArray[_index]._radius = radius;
74 | _deferredCircleArray[_index]._axis = axis;
75 | _deferredCircleArray[_index]._center = center;
76 | _deferredCircleArray[_index]._color = color;
77 | _deferredCircleArray[_index]._segments = segments;
78 | _deferredCircleArray[_index]._filled = filled;
79 | _deferredCircleArray[_index]._in3D = in3D;
80 | _index++;
81 | }
82 | }
83 |
84 | public static void DrawAll()
85 | {
86 | // draw all circles in the buffer
87 | for (int i = 0; i < _index; i++)
88 | {
89 | DeferredCircle dc = _deferredCircleArray[i];
90 | Drawing.DrawCircleOrDisk(dc._radius, dc._axis, dc._center, dc._color, dc._segments, dc._filled, dc._in3D);
91 | }
92 |
93 | // reset buffer index
94 | _index = 0;
95 | }
96 |
97 | float _radius;
98 | Vector3 _axis;
99 | Vector3 _center;
100 | Color _color;
101 | int _segments;
102 | bool _filled;
103 | bool _in3D;
104 |
105 | static int _index = 0;
106 | const int SIZE = 500;
107 | static readonly DeferredCircle[] _deferredCircleArray;
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/Demo/Extensions.cs:
--------------------------------------------------------------------------------
1 | using System.Numerics;
2 | using System.Runtime.CompilerServices;
3 |
4 | namespace Demo
5 | {
6 | static class Extensions
7 | {
8 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
9 | public static Vector3 FromXna(this Microsoft.Xna.Framework.Vector3 v)
10 | {
11 | return new Vector3(v.X, v.Y, v.Z);
12 | }
13 |
14 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
15 | public static Microsoft.Xna.Framework.Vector3 ToXna(this Vector3 v)
16 | {
17 | return new Microsoft.Xna.Framework.Vector3(v.X, v.Y, v.Z);
18 | }
19 |
20 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
21 | public static Vector2 FromXna(this Microsoft.Xna.Framework.Vector2 v)
22 | {
23 | return new Vector2(v.X, v.Y);
24 | }
25 |
26 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
27 | public static Microsoft.Xna.Framework.Vector2 ToXna(this Vector2 v)
28 | {
29 | return new Microsoft.Xna.Framework.Vector2(v.X, v.Y);
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Demo/IPlugIn.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // All rights reserved.
5 | //
6 | // This software is licensed as described in the file license.txt, which
7 | // you should have received as part of this distribution. The terms
8 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
9 |
10 | using System;
11 | using System.Collections.Generic;
12 | using Microsoft.Xna.Framework.Input;
13 | using SharpSteer2;
14 |
15 | namespace Demo
16 | {
17 | public interface IPlugIn
18 | {
19 | // generic PlugIn actions: open, update, redraw, close and reset
20 | void Open();
21 | void Update(float currentTime, float elapsedTime);
22 | void Redraw(float currentTime, float elapsedTime);
23 | void Close();
24 | void Reset();
25 |
26 | // return a pointer to this instance's character string name
27 | String Name { get; }
28 |
29 | // numeric sort key used to establish user-visible PlugIn ordering
30 | // ("built ins" have keys greater than 0 and less than 1)
31 | float SelectionOrderSortKey { get; }
32 |
33 | // allows a PlugIn to nominate itself as OpenSteerDemo's initially selected
34 | // (default) PlugIn, which is otherwise the first in "selection order"
35 | bool RequestInitialSelection { get; }
36 |
37 | // handle function keys (which are reserved by SterTest for PlugIns)
38 | void HandleFunctionKeys(Keys key);
39 |
40 | // print "mini help" documenting function keys handled by this PlugIn
41 | void PrintMiniHelpForFunctionKeys();
42 |
43 | // return an AVGroup (an STL vector of AbstractVehicle pointers) of
44 | // all vehicles(/agents/characters) defined by the PlugIn
45 | IEnumerable Vehicles { get; }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Demo/PlugIn.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // All rights reserved.
5 | //
6 | // This software is licensed as described in the file license.txt, which
7 | // you should have received as part of this distribution. The terms
8 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
9 |
10 | using System;
11 | using System.Collections.Generic;
12 | using Microsoft.Xna.Framework.Input;
13 | using SharpSteer2;
14 |
15 | namespace Demo
16 | {
17 | public abstract class PlugIn : IPlugIn
18 | {
19 | public abstract void Open();
20 | public abstract void Update(float currentTime, float elapsedTime);
21 | public abstract void Redraw(float currentTime, float elapsedTime);
22 | public abstract void Close();
23 | public abstract String Name { get; }
24 | public abstract IEnumerable Vehicles { get; }
25 |
26 | // prototypes for function pointers used with PlugIns
27 | public delegate void PlugInCallBackFunction(PlugIn clientObject);
28 | public delegate void VoidCallBackFunction();
29 | public delegate void TimestepCallBackFunction(float currentTime, float elapsedTime);
30 |
31 | protected readonly IAnnotationService Annotations;
32 |
33 | // constructor
34 | protected PlugIn(IAnnotationService annotations)
35 | {
36 | Annotations = annotations;
37 |
38 | // save this new instance in the registry
39 | AddToRegistry();
40 | }
41 |
42 | // default reset method is to do a close then an open
43 | public virtual void Reset()
44 | {
45 | Close();
46 | Open();
47 | }
48 |
49 | // default sort key (after the "built ins")
50 | public virtual float SelectionOrderSortKey { get { return 1.0f; } }
51 |
52 | // default is to NOT request to be initially selected
53 | public virtual bool RequestInitialSelection { get { return false; } }
54 |
55 | // default function key handler: ignore all
56 | public virtual void HandleFunctionKeys(Keys key) { }
57 |
58 | // default "mini help": print nothing
59 | public virtual void PrintMiniHelpForFunctionKeys() { }
60 |
61 | // returns pointer to the next PlugIn in "selection order"
62 | public PlugIn Next()
63 | {
64 | for (int i = 0; i < _itemsInRegistry; i++)
65 | {
66 | if (this == _registry[i])
67 | {
68 | bool atEnd = (i == (_itemsInRegistry - 1));
69 | return _registry[atEnd ? 0 : i + 1];
70 | }
71 | }
72 | return null;
73 | }
74 |
75 | // format instance to characters for printing to stream
76 | public override string ToString()
77 | {
78 | return String.Format("", Name);
79 | }
80 |
81 | // CLASS FUNCTIONS
82 |
83 | // search the class registry for a Plugin with the given name
84 | public static IPlugIn FindByName(String name)
85 | {
86 | if (String.IsNullOrEmpty(name) == false)
87 | {
88 | for (int i = 0; i < _itemsInRegistry; i++)
89 | {
90 | PlugIn pi = _registry[i];
91 | String s = pi.Name;
92 | if (String.IsNullOrEmpty(s) && name == s)
93 | return pi;
94 | }
95 | }
96 | return null;
97 | }
98 |
99 | // apply a given function to all PlugIns in the class registry
100 | public static void ApplyToAll(PlugInCallBackFunction f)
101 | {
102 | for (int i = 0; i < _itemsInRegistry; i++)
103 | {
104 | f(_registry[i]);
105 | }
106 | }
107 |
108 | // sort PlugIn registry by "selection order"
109 | public static void SortBySelectionOrder()
110 | {
111 | // I know, I know, just what the world needs:
112 | // another inline shell sort implementation...
113 |
114 | // starting at each of the first n-1 elements of the array
115 | for (int i = 0; i < _itemsInRegistry - 1; i++)
116 | {
117 | // scan over subsequent pairs, swapping if larger value is first
118 | for (int j = i + 1; j < _itemsInRegistry; j++)
119 | {
120 | float iKey = _registry[i].SelectionOrderSortKey;
121 | float jKey = _registry[j].SelectionOrderSortKey;
122 |
123 | if (iKey > jKey)
124 | {
125 | PlugIn temporary = _registry[i];
126 | _registry[i] = _registry[j];
127 | _registry[j] = temporary;
128 | }
129 | }
130 | }
131 | }
132 |
133 | // returns pointer to default PlugIn (currently, first in registry)
134 | public static PlugIn FindDefault()
135 | {
136 | // return NULL if no PlugIns exist
137 | if (_itemsInRegistry == 0) return null;
138 |
139 | // otherwise, return the first PlugIn that requests initial selection
140 | for (int i = 0; i < _itemsInRegistry; i++)
141 | {
142 | if (_registry[i].RequestInitialSelection) return _registry[i];
143 | }
144 |
145 | // otherwise, return the "first" PlugIn (in "selection order")
146 | return _registry[0];
147 | }
148 |
149 | // save this instance in the class's registry of instances
150 | void AddToRegistry()
151 | {
152 | // save this instance in the registry
153 | _registry[_itemsInRegistry++] = this;
154 | }
155 |
156 | // This array stores a list of all PlugIns. It is manipulated by the
157 | // constructor and destructor, and used in findByName and applyToAll.
158 | const int TOTAL_SIZE_OF_REGISTRY = 1000;
159 | static int _itemsInRegistry = 0;
160 | static readonly PlugIn[] _registry = new PlugIn[TOTAL_SIZE_OF_REGISTRY];
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/Demo/PlugIns/AirCombat/AirCombatPlugin.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using Microsoft.Xna.Framework;
4 | using SharpSteer2;
5 | using SharpSteer2.Database;
6 | using SharpSteer2.Helpers;
7 | using Vector3 = System.Numerics.Vector3;
8 |
9 | namespace Demo.PlugIns.AirCombat
10 | {
11 | class AirCombatPlugin
12 | :PlugIn
13 | {
14 | private readonly List _team1 = new List();
15 | private readonly List _team2 = new List();
16 |
17 | private readonly List _missiles = new List();
18 |
19 | private IProximityDatabase _pd;
20 |
21 | public AirCombatPlugin(IAnnotationService annotations)
22 | :base(annotations)
23 | {
24 | }
25 |
26 | public override void Open()
27 | {
28 | CreateDatabase();
29 | _missiles.Clear();
30 |
31 | _team1.Add(new Fighter(_pd, Annotations, FireMissile)
32 | {
33 | Position = new Vector3(20, 0, 0),
34 | Forward = Vector3Helpers.RandomUnitVector(),
35 | Color = Color.Green,
36 | Enemy = _team2
37 | });
38 | _team1.Add(new Fighter(_pd, Annotations, FireMissile)
39 | {
40 | Position = new Vector3(15, 0, 5),
41 | Forward = Vector3Helpers.RandomUnitVector(),
42 | Color = Color.Green,
43 | Enemy = _team2
44 | });
45 | _team1.Add(new Fighter(_pd, Annotations, FireMissile)
46 | {
47 | Position = new Vector3(15, 0, -5),
48 | Forward = Vector3Helpers.RandomUnitVector(),
49 | Color = Color.Green,
50 | Enemy = _team2
51 | });
52 |
53 | _team2.Add(new Fighter(_pd, Annotations, FireMissile)
54 | {
55 | Position = new Vector3(-20, 0, 0),
56 | Forward = Vector3Helpers.RandomUnitVector(),
57 | Color = Color.Blue,
58 | Enemy = _team1
59 | });
60 | _team2.Add(new Fighter(_pd, Annotations, FireMissile)
61 | {
62 | Position = new Vector3(-15, 0, 5),
63 | Forward = Vector3Helpers.RandomUnitVector(),
64 | Color = Color.Blue,
65 | Enemy = _team1
66 | });
67 | _team2.Add(new Fighter(_pd, Annotations, FireMissile)
68 | {
69 | Position = new Vector3(-15, 0, -5),
70 | Forward = Vector3Helpers.RandomUnitVector(),
71 | Color = Color.Blue,
72 | Enemy = _team1
73 | });
74 | }
75 |
76 | private void CreateDatabase()
77 | {
78 | Vector3 center = Vector3.Zero;
79 | const float DIV = 10.0f;
80 | Vector3 divisions = new Vector3(DIV, DIV, DIV);
81 | const float DIAMETER = Fighter.WORLD_RADIUS * 2;
82 | Vector3 dimensions = new Vector3(DIAMETER, DIAMETER, DIAMETER);
83 | _pd = new LocalityQueryProximityDatabase(center, dimensions, divisions);
84 | }
85 |
86 | private void FireMissile(Fighter launcher, Fighter target)
87 | {
88 | if (_missiles.Count(m => m.Target == target) < 3)
89 | {
90 | _missiles.Add(new Missile(_pd, target, Annotations)
91 | {
92 | Position = launcher.Position,
93 | Forward = Vector3.Normalize(launcher.Forward * 0.9f + Vector3Helpers.RandomUnitVector() * 0.1f),
94 | Speed = launcher.Speed,
95 | Color = _team1.Contains(launcher) ? Color.Black : Color.White
96 | });
97 | }
98 | }
99 |
100 | public override void Update(float currentTime, float elapsedTime)
101 | {
102 | foreach (var fighter in _team1)
103 | fighter.Update(currentTime, elapsedTime);
104 | foreach (var fighter in _team2)
105 | fighter.Update(currentTime, elapsedTime);
106 |
107 | foreach (var missile in _missiles)
108 | missile.Update(currentTime, elapsedTime);
109 | _missiles.RemoveAll(m => m.IsDead);
110 | }
111 |
112 | public override void Redraw(float currentTime, float elapsedTime)
113 | {
114 | Demo.UpdateCamera(elapsedTime, _team1[0]);
115 |
116 | foreach (var fighter in _team1)
117 | fighter.Draw();
118 | foreach (var fighter in _team2)
119 | fighter.Draw();
120 |
121 | foreach (var missile in _missiles)
122 | missile.Draw();
123 | }
124 |
125 | public override void Close()
126 | {
127 | _team1.Clear();
128 | _team2.Clear();
129 | _missiles.Clear();
130 | _pd = null;
131 | }
132 |
133 | public override string Name
134 | {
135 | get { return "Air Combat"; }
136 | }
137 |
138 | public override IEnumerable Vehicles
139 | {
140 | get
141 | {
142 | foreach (var fighter in _team1)
143 | yield return fighter;
144 | foreach (var fighter in _team2)
145 | yield return fighter;
146 | foreach (var missile in _missiles)
147 | yield return missile;
148 | }
149 | }
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/Demo/PlugIns/AirCombat/Fighter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Microsoft.Xna.Framework;
5 | using SharpSteer2;
6 | using SharpSteer2.Database;
7 | using SharpSteer2.Helpers;
8 | using Vector3 = System.Numerics.Vector3;
9 |
10 | namespace Demo.PlugIns.AirCombat
11 | {
12 | class Fighter
13 | :SimpleVehicle
14 | {
15 | private readonly Trail _trail;
16 | private readonly ITokenForProximityDatabase _proximityToken;
17 |
18 | public List Enemy { get; set; }
19 | private readonly List _neighbours = new List();
20 |
21 | public override float MaxForce
22 | {
23 | get { return 7; }
24 | }
25 | public override float MaxSpeed
26 | {
27 | get { return 15; }
28 | }
29 |
30 | public const float WORLD_RADIUS = 30;
31 |
32 | private float _lastFired = -100;
33 | private const float REFIRE_TIME = 2f;
34 | private readonly Action _fireMissile;
35 |
36 | public Color Color = Color.White;
37 |
38 | public Fighter(IProximityDatabase proximity, IAnnotationService annotation, Action fireMissile)
39 | :base(annotation)
40 | {
41 | _trail = new Trail(5, 50)
42 | {
43 | TrailColor = Color.WhiteSmoke,
44 | TickColor = Color.LightGray
45 | };
46 | _proximityToken = proximity.AllocateToken(this);
47 |
48 | _fireMissile = fireMissile;
49 | }
50 |
51 | public void Update(float currentTime, float elapsedTime)
52 | {
53 | _trail.Record(currentTime, Position);
54 |
55 | _neighbours.Clear();
56 | _proximityToken.FindNeighbors(Position, 50, _neighbours);
57 |
58 | var target = ClosestEnemy(_neighbours);
59 |
60 | //if (Vector3.Dot(Vector3.Normalize(Enemy.Position - Position), Forward) > 0.7f)
61 | {
62 | if (currentTime - _lastFired > REFIRE_TIME && target != null)
63 | {
64 | _fireMissile(this, ClosestEnemy(_neighbours));
65 | _lastFired = currentTime;
66 | }
67 | }
68 |
69 | Vector3 otherPlaneForce = SteerToAvoidCloseNeighbors(3, _neighbours);
70 | if (target != null)
71 | otherPlaneForce += SteerForPursuit(target);
72 |
73 | var boundary = HandleBoundary();
74 |
75 | var evasion = _neighbours
76 | .Where(v => v is Missile)
77 | .Cast()
78 | .Where(m => m.Target == this)
79 | .Select(m => SteerForEvasion(m, 1))
80 | .Aggregate(Vector3.Zero, (a, b) => a + b);
81 |
82 | ApplySteeringForce(otherPlaneForce + boundary + evasion * 0.5f + SteerForWander(elapsedTime) * 0.1f, elapsedTime);
83 |
84 | _proximityToken.UpdateForNewPosition(Position);
85 | }
86 |
87 | private Fighter ClosestEnemy(List neighbours)
88 | {
89 | if (_neighbours.Count == 0)
90 | return null;
91 |
92 | var enemyFighterNeighbours = _neighbours
93 | .Where(v => v is Fighter)
94 | .Cast()
95 | .Where(f => f.Enemy != Enemy);
96 |
97 | if (!enemyFighterNeighbours.Any())
98 | return null;
99 |
100 | return enemyFighterNeighbours
101 | .Select(f => new { Distance = (Position - f.Position).LengthSquared(), Fighter = f })
102 | .Aggregate((a, b) => a.Distance < b.Distance ? a : b)
103 | .Fighter;
104 | }
105 |
106 | protected override void RegenerateLocalSpace(Vector3 newVelocity, float elapsedTime)
107 | {
108 | RegenerateLocalSpaceForBanking(newVelocity, elapsedTime);
109 | }
110 |
111 | private Vector3 HandleBoundary()
112 | {
113 | // while inside the sphere do noting
114 | if (Position.Length() < WORLD_RADIUS)
115 | return Vector3.Zero;
116 |
117 | // steer back when outside
118 | Vector3 seek = SteerForSeek(Vector3.Zero);
119 | Vector3 lateral = Vector3Helpers.PerpendicularComponent(seek, Forward);
120 | return lateral;
121 |
122 | }
123 |
124 | public void Draw()
125 | {
126 | _trail.Draw(annotation);
127 | Drawing.DrawBasic3dSphericalVehicle(this, Color);
128 | }
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/Demo/PlugIns/AirCombat/Missile.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Xna.Framework;
2 | using SharpSteer2;
3 | using SharpSteer2.Database;
4 |
5 | namespace Demo.PlugIns.AirCombat
6 | {
7 | class Missile
8 | :SimpleVehicle
9 | {
10 | private readonly Trail _trail;
11 | private ITokenForProximityDatabase _proximityToken;
12 |
13 | public readonly IVehicle Target;
14 |
15 | public bool IsDead
16 | {
17 | get { return _timer <= 0; }
18 | }
19 | private float _timer = 15;
20 |
21 | public override float MaxForce
22 | {
23 | get { return 400; }
24 | }
25 | public override float MaxSpeed
26 | {
27 | get { return 50; }
28 | }
29 |
30 | public Color Color = Color.Red;
31 |
32 | public Missile(IProximityDatabase proximity, IVehicle target, IAnnotationService annotation)
33 | :base(annotation)
34 | {
35 | _trail = new Trail(1, 10)
36 | {
37 | TrailColor = Color.Red,
38 | TickColor = Color.DarkRed
39 | };
40 | _proximityToken = proximity.AllocateToken(this);
41 | Target = target;
42 | }
43 |
44 | public void Update(float currentTime, float elapsedTime)
45 | {
46 | _timer -= elapsedTime;
47 | if (!IsDead)
48 | {
49 | _trail.Record(currentTime, Position);
50 | ApplySteeringForce(SteerForPursuit(Target, 1) * 0.95f + SteerForWander(elapsedTime) * 0.05f, elapsedTime);
51 | _proximityToken.UpdateForNewPosition(Position);
52 | }
53 | else if (_proximityToken != null)
54 | {
55 | _proximityToken.Dispose();
56 | _proximityToken = null;
57 | }
58 | }
59 |
60 | public void Draw()
61 | {
62 | _trail.Draw(annotation);
63 | Drawing.DrawBasic3dSphericalVehicle(this, Color);
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/Demo/PlugIns/Arrival/ArrivalPlugIn.cs:
--------------------------------------------------------------------------------
1 | using Demo.PlugIns.Ctf;
2 | using SharpSteer2;
3 |
4 | namespace Demo.PlugIns.Arrival
5 | {
6 | public class ArrivalPlugIn
7 | : CtfPlugIn
8 | {
9 | public override string Name
10 | {
11 | get { return "Arrival"; }
12 | }
13 |
14 | public ArrivalPlugIn(IAnnotationService annotations)
15 | :base(annotations, 0, true, 0.5f, 100)
16 | {
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Demo/PlugIns/Ctf/CtfBase.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // Copyright (C) 2007 Michael Coles
5 | // All rights reserved.
6 | //
7 | // This software is licensed as described in the file license.txt, which
8 | // you should have received as part of this distribution. The terms
9 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
10 |
11 | using System.Collections.Generic;
12 | using System.Linq;
13 | using Microsoft.Xna.Framework;
14 | using SharpSteer2;
15 | using SharpSteer2.Helpers;
16 | using SharpSteer2.Obstacles;
17 | using Vector3 = System.Numerics.Vector3;
18 |
19 | namespace Demo.PlugIns.Ctf
20 | { // spherical obstacle group
21 |
22 | public class CtfBase : SimpleVehicle
23 | {
24 | protected readonly CtfPlugIn Plugin;
25 | private readonly float _baseRadius;
26 |
27 | protected Trail Trail;
28 |
29 | public override float MaxForce { get { return 3; } }
30 | public override float MaxSpeed { get { return 3; } }
31 |
32 | // constructor
33 | protected CtfBase(CtfPlugIn plugin, IAnnotationService annotations = null, float baseRadius = 1.5f)
34 | :base(annotations)
35 | {
36 | Plugin = plugin;
37 | _baseRadius = baseRadius;
38 |
39 | Reset();
40 | }
41 |
42 | // reset state
43 | public override void Reset()
44 | {
45 | base.Reset(); // reset the vehicle
46 |
47 | Speed = 3; // speed along Forward direction.
48 |
49 | Avoiding = false; // not actively avoiding
50 |
51 | RandomizeStartingPositionAndHeading(); // new starting position
52 |
53 | Trail = new Trail();
54 | Trail.Clear(); // prevent long streaks due to teleportation
55 | }
56 |
57 | // draw this character/vehicle into the scene
58 | public virtual void Draw()
59 | {
60 | Drawing.DrawBasic2dCircularVehicle(this, BodyColor);
61 | Trail.Draw(annotation);
62 | }
63 |
64 | // annotate when actively avoiding obstacles
65 | // xxx perhaps this should be a call to a general purpose annotation
66 | // xxx for "local xxx axis aligned box in XZ plane" -- same code in in
67 | // xxx Pedestrian.cpp
68 | public void AnnotateAvoidObstacle(float minDistanceToCollision)
69 | {
70 | Vector3 boxSide = Side * Radius;
71 | Vector3 boxFront = Forward * minDistanceToCollision;
72 | Vector3 fr = Position + boxFront - boxSide;
73 | Vector3 fl = Position + boxFront + boxSide;
74 | Vector3 br = Position - boxSide;
75 | Vector3 bl = Position + boxSide;
76 | annotation.Line(fr, fl, Color.White.ToVector3().FromXna());
77 | annotation.Line(fl, bl, Color.White.ToVector3().FromXna());
78 | annotation.Line(bl, br, Color.White.ToVector3().FromXna());
79 | annotation.Line(br, fr, Color.White.ToVector3().FromXna());
80 | }
81 |
82 | public void DrawHomeBase()
83 | {
84 | Vector3 up = new Vector3(0, 0.01f, 0);
85 | Color atColor = new Color((byte)(255.0f * 0.3f), (byte)(255.0f * 0.3f), (byte)(255.0f * 0.5f));
86 | Color noColor = Color.Gray;
87 | bool reached = Plugin.CtfSeeker.State == SeekerState.AtGoal;
88 | Color baseColor = (reached ? atColor : noColor);
89 | Drawing.DrawXZDisk(_baseRadius, Globals.HomeBaseCenter, baseColor, 40);
90 | Drawing.DrawXZDisk(_baseRadius / 15, Globals.HomeBaseCenter + up, Color.Black, 20);
91 | }
92 |
93 | private void RandomizeStartingPositionAndHeading()
94 | {
95 | // randomize position on a ring between inner and outer radii
96 | // centered around the home base
97 | float rRadius = RandomHelpers.Random(Globals.MIN_START_RADIUS, Globals.MAX_START_RADIUS);
98 | Vector3 randomOnRing = Vector3Helpers.RandomUnitVectorOnXZPlane() * rRadius;
99 | Position = (Globals.HomeBaseCenter + randomOnRing);
100 |
101 | // are we are too close to an obstacle?
102 | if (MinDistanceToObstacle(Position) < Radius * 5)
103 | {
104 | // if so, retry the randomization (this recursive call may not return
105 | // if there is too little free space)
106 | RandomizeStartingPositionAndHeading();
107 | }
108 | else
109 | {
110 | // otherwise, if the position is OK, randomize 2D heading
111 | RandomizeHeadingOnXZPlane();
112 | }
113 | }
114 |
115 | public enum SeekerState
116 | {
117 | Running,
118 | Tagged,
119 | AtGoal
120 | }
121 |
122 | // for draw method
123 | protected Color BodyColor;
124 |
125 | // xxx store steer sub-state for anotation
126 | protected bool Avoiding;
127 |
128 | // dynamic obstacle registry
129 | public static void InitializeObstacles(float radius, int obstacles)
130 | {
131 | // start with 40% of possible obstacles
132 | if (ObstacleCount == -1)
133 | {
134 | ObstacleCount = 0;
135 | for (int i = 0; i < obstacles; i++)
136 | AddOneObstacle(radius);
137 | }
138 | }
139 |
140 | public static void AddOneObstacle(float radius)
141 | {
142 | // pick a random center and radius,
143 | // loop until no overlap with other obstacles and the home base
144 | float r;
145 | Vector3 c;
146 | float minClearance;
147 | float requiredClearance = Globals.Seeker.Radius * 4; // 2 x diameter
148 | do
149 | {
150 | r = RandomHelpers.Random(1.5f, 4);
151 | c = Vector3Helpers.RandomVectorOnUnitRadiusXZDisk() * Globals.MAX_START_RADIUS * 1.1f;
152 | minClearance = AllObstacles.Aggregate(float.MaxValue, (current, t) => TestOneObstacleOverlap(current, r, t.Radius, c, t.Center));
153 |
154 | minClearance = TestOneObstacleOverlap(minClearance, r, radius - requiredClearance, c, Globals.HomeBaseCenter);
155 | }
156 | while (minClearance < requiredClearance);
157 |
158 | // add new non-overlapping obstacle to registry
159 | AllObstacles.Add(new SphericalObstacle(r, c));
160 | ObstacleCount++;
161 | }
162 |
163 | public static void RemoveOneObstacle()
164 | {
165 | if (ObstacleCount <= 0)
166 | return;
167 |
168 | ObstacleCount--;
169 | AllObstacles.RemoveAt(ObstacleCount);
170 | }
171 |
172 | private static float MinDistanceToObstacle(Vector3 point)
173 | {
174 | const float R = 0;
175 | Vector3 c = point;
176 | return AllObstacles.Aggregate(float.MaxValue, (current, t) => TestOneObstacleOverlap(current, R, t.Radius, c, t.Center));
177 | }
178 |
179 | static float TestOneObstacleOverlap(float minClearance, float r, float radius, Vector3 c, Vector3 center)
180 | {
181 | float d = Vector3.Distance(c, center);
182 | float clearance = d - (r + radius);
183 | if (minClearance > clearance) minClearance = clearance;
184 | return minClearance;
185 | }
186 |
187 | protected static int ObstacleCount = -1;
188 | public static readonly List AllObstacles = new List();
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/Demo/PlugIns/Ctf/CtfEnemy.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // Copyright (C) 2007 Michael Coles
5 | // All rights reserved.
6 | //
7 | // This software is licensed as described in the file license.txt, which
8 | // you should have received as part of this distribution. The terms
9 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
10 |
11 | using Microsoft.Xna.Framework;
12 | using SharpSteer2;
13 | using Vector3 = System.Numerics.Vector3;
14 |
15 | namespace Demo.PlugIns.Ctf
16 | {
17 | public class CtfEnemy : CtfBase
18 | {
19 | // constructor
20 | public CtfEnemy(CtfPlugIn plugin, IAnnotationService annotations = null)
21 | : base(plugin, annotations)
22 | {
23 | Reset();
24 | }
25 |
26 | // reset state
27 | public override void Reset()
28 | {
29 | base.Reset();
30 | BodyColor = new Color((byte)(255.0f * 0.6f), (byte)(255.0f * 0.4f), (byte)(255.0f * 0.4f)); // redish
31 | }
32 |
33 | // per frame simulation update
34 | public void Update(float currentTime, float elapsedTime)
35 | {
36 | // determine upper bound for pursuit prediction time
37 | float seekerToGoalDist = Vector3.Distance(Globals.HomeBaseCenter, Globals.Seeker.Position);
38 | float adjustedDistance = seekerToGoalDist - Radius - Plugin.BaseRadius;
39 | float seekerToGoalTime = ((adjustedDistance < 0) ? 0 : (adjustedDistance / Globals.Seeker.Speed));
40 | float maxPredictionTime = seekerToGoalTime * 0.9f;
41 |
42 | // determine steering (pursuit, obstacle avoidance, or braking)
43 | Vector3 steer = Vector3.Zero;
44 | if (Globals.Seeker.State == SeekerState.Running)
45 | {
46 | Vector3 avoidance = SteerToAvoidObstacles(Globals.AVOIDANCE_PREDICT_TIME_MIN, AllObstacles);
47 |
48 | // saved for annotation
49 | Avoiding = (avoidance == Vector3.Zero);
50 |
51 | steer = Avoiding ? SteerForPursuit(Globals.Seeker, maxPredictionTime) : avoidance;
52 | }
53 | else
54 | {
55 | ApplyBrakingForce(Globals.BRAKING_RATE, elapsedTime);
56 | }
57 | ApplySteeringForce(steer, elapsedTime);
58 |
59 | // annotation
60 | annotation.VelocityAcceleration(this);
61 | Trail.Record(currentTime, Position);
62 |
63 | // detect and record interceptions ("tags") of seeker
64 | float seekerToMeDist = Vector3.Distance(Position, Globals.Seeker.Position);
65 | float sumOfRadii = Radius + Globals.Seeker.Radius;
66 | if (seekerToMeDist < sumOfRadii)
67 | {
68 | if (Globals.Seeker.State == SeekerState.Running) Globals.Seeker.State = SeekerState.Tagged;
69 |
70 | // annotation:
71 | if (Globals.Seeker.State == SeekerState.Tagged)
72 | {
73 | Color color = new Color((byte)(255.0f * 0.8f), (byte)(255.0f * 0.5f), (byte)(255.0f * 0.5f));
74 | annotation.DiskXZ(sumOfRadii, (Position + Globals.Seeker.Position) / 2, color.ToVector3().FromXna(), 20);
75 | }
76 | }
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/Demo/PlugIns/Ctf/Globals.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // Copyright (C) 2007 Michael Coles
5 | // All rights reserved.
6 | //
7 | // This software is licensed as described in the file license.txt, which
8 | // you should have received as part of this distribution. The terms
9 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
10 |
11 | using Microsoft.Xna.Framework;
12 | using Vector3 = System.Numerics.Vector3;
13 |
14 | namespace Demo.PlugIns.Ctf
15 | {
16 | class Globals
17 | {
18 | public static readonly Vector3 HomeBaseCenter = new Vector3(0, 0, 0);
19 |
20 | public const float MIN_START_RADIUS = 30;
21 | public const float MAX_START_RADIUS = 40;
22 |
23 | public const float BRAKING_RATE = 0.75f;
24 |
25 | public static readonly Color EvadeColor = new Color((byte)(255.0f * 0.6f), (byte)(255.0f * 0.6f), (byte)(255.0f * 0.3f)); // annotation
26 | public static readonly Color SeekColor = new Color((byte)(255.0f * 0.3f), (byte)(255.0f * 0.6f), (byte)(255.0f * 0.6f)); // annotation
27 | public static readonly Color ClearPathColor = new Color((byte)(255.0f * 0.3f), (byte)(255.0f * 0.6f), (byte)(255.0f * 0.3f)); // annotation
28 |
29 | public const float AVOIDANCE_PREDICT_TIME_MIN = 0.9f;
30 | public const float AVOIDANCE_PREDICT_TIME_MAX = 2;
31 | public static float AvoidancePredictTime = AVOIDANCE_PREDICT_TIME_MIN;
32 |
33 | public static CtfSeeker Seeker = null;
34 |
35 | // count the number of times the simulation has reset (e.g. for overnight runs)
36 | public static int ResetCount = 0;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Demo/PlugIns/FlowField/FlowFieldFollower.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Demo.PlugIns.Ctf;
3 | using Microsoft.Xna.Framework;
4 | using SharpSteer2;
5 | using SharpSteer2.Database;
6 | using SharpSteer2.Helpers;
7 | using Vector3 = System.Numerics.Vector3;
8 |
9 | namespace Demo.PlugIns.FlowField
10 | {
11 | public class FlowFieldFollower
12 | : SimpleVehicle
13 | {
14 | private readonly FlowFieldPlugIn _plugin;
15 | private Trail _trail;
16 |
17 | private readonly ITokenForProximityDatabase _proximityToken;
18 |
19 | public override float MaxSpeed { get { return 2; } }
20 | public override float MaxForce { get { return 4; } }
21 |
22 | public FlowFieldFollower(FlowFieldPlugIn plugin)
23 | : base(plugin.Annotations)
24 | {
25 | _plugin = plugin;
26 |
27 | _proximityToken = plugin.Database.AllocateToken(this);
28 | }
29 |
30 | public override void Reset()
31 | {
32 | base.Reset();
33 |
34 | RandomizeStartingPositionAndHeading(); // new starting position
35 |
36 | _trail = new Trail(7.5f, 600);
37 | _trail.Clear();
38 | }
39 |
40 | private void RandomizeStartingPositionAndHeading()
41 | {
42 | // randomize position on a ring between inner and outer radii
43 | // centered around the home base
44 | float rRadius = RandomHelpers.Random(10, 50);
45 | Vector3 randomOnRing = Vector3Helpers.RandomUnitVectorOnXZPlane() * rRadius;
46 | Position = (Globals.HomeBaseCenter + randomOnRing);
47 | RandomizeHeadingOnXZPlane();
48 | }
49 |
50 | public void Update(float currentTime, float elapsedTime)
51 | {
52 | ApplySteeringForce(SteeringForce(), elapsedTime);
53 |
54 | annotation.VelocityAcceleration(this);
55 | _trail.Record(currentTime, Position);
56 |
57 | _proximityToken.UpdateForNewPosition(Position);
58 | }
59 |
60 | private Vector3 SteeringForce()
61 | {
62 | if (Position.X > 25 || Position.X < -25 || Position.Z > 25 || Position.Z < -25)
63 | return SteerForSeek(Vector3.Zero);
64 |
65 | var flowField = SteerToFollowFlowField(_plugin.FlowField, _plugin.PredictionTime);
66 |
67 | const float CA_LEAD_TIME = 3;
68 |
69 | // find all neighbors within maxRadius using proximity database
70 | // (radius is largest distance between vehicles traveling head-on
71 | // where a collision is possible within caLeadTime seconds.)
72 | float maxRadius = CA_LEAD_TIME * MaxSpeed * 2;
73 | var neighbours = new List();
74 | _proximityToken.FindNeighbors(Position, maxRadius, neighbours);
75 |
76 | if (neighbours.Count > 0)
77 | {
78 | var avoid = SteerToAvoidNeighbors(CA_LEAD_TIME, neighbours) * 10;
79 | if (avoid != Vector3.Zero)
80 | return avoid;
81 | }
82 |
83 | return flowField;
84 | }
85 |
86 | protected override Vector3 AdjustRawSteeringForce(Vector3 force, float deltaTime)
87 | {
88 | return base.AdjustRawSteeringForce(new Vector3(force.X, 0, force.Z), deltaTime);
89 | }
90 |
91 | internal void Draw()
92 | {
93 | Drawing.DrawBasic2dCircularVehicle(this, Color.GhostWhite);
94 | _trail.Draw(annotation);
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/Demo/PlugIns/FlowField/FlowFieldPlugIn.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using Microsoft.Xna.Framework;
4 | using SharpSteer2;
5 | using SharpSteer2.Database;
6 | using Vector3 = System.Numerics.Vector3;
7 |
8 | namespace Demo.PlugIns.FlowField
9 | {
10 | public class FlowFieldPlugIn
11 | : PlugIn
12 | {
13 | private const int FOLLOWER_COUNT = 15;
14 | private readonly List _followers = new List(FOLLOWER_COUNT);
15 |
16 | public IFlowField FlowField { get; private set; }
17 | public float PredictionTime { get; private set; }
18 |
19 | public IProximityDatabase Database { get; private set; }
20 |
21 | public override IEnumerable Vehicles
22 | {
23 | get { return _followers; }
24 | }
25 |
26 | public new IAnnotationService Annotations
27 | {
28 | get { return base.Annotations; }
29 | }
30 |
31 | public override string Name
32 | {
33 | get { return "Flow Field Following"; }
34 | }
35 |
36 | public FlowFieldPlugIn(IAnnotationService annotations) : base(annotations)
37 | {
38 | PredictionTime = 1;
39 | Database = new LocalityQueryProximityDatabase(Vector3.Zero, new Vector3(250, 250, 250), new Vector3(10));
40 | }
41 |
42 | public override void Open()
43 | {
44 | // create the specified number of enemies,
45 | // storing pointers to them in an array.
46 | for (int i = 0; i < FOLLOWER_COUNT; i++)
47 | _followers.Add(new FlowFieldFollower(this));
48 |
49 | // initialize camera
50 | Demo.Init2dCamera(_followers.First());
51 | Demo.Camera.Mode = Camera.CameraMode.Fixed;
52 | Demo.Camera.FixedTarget = Vector3.Zero;
53 | Demo.Camera.FixedTarget.X = 15;
54 | Demo.Camera.FixedPosition.X = 80;
55 | Demo.Camera.FixedPosition.Y = 60;
56 | Demo.Camera.FixedPosition.Z = 0;
57 |
58 | FlowField = GenerateFlowField();
59 | }
60 |
61 | private static IFlowField GenerateFlowField()
62 | {
63 | var f = new SimpleFlowField(50, 1, 50, new Vector3(25, 0.5f, 25));
64 |
65 | //Start random
66 | f.Randomize(1);
67 |
68 | //Swirl around center
69 | //Half the field is a swirl (basically just concentric circles) while the other half has a slight bias to spiral inwards towards the center
70 | f.Func(pos => Vector3.Lerp(pos / 5, Vector3.Normalize(Vector3.Cross(pos, Vector3.UnitY)), pos.X > 0.5f ? 0.75f : 0.9f), 0.85f);
71 |
72 | //Keep it flat on the plane
73 | f.ClampXZ();
74 |
75 | //Clean NaN values
76 | f.Clean();
77 |
78 | return f;
79 | }
80 |
81 | public override void Update(float currentTime, float elapsedTime)
82 | {
83 | foreach (var flowFieldFollower in _followers)
84 | {
85 | flowFieldFollower.Update(currentTime, elapsedTime);
86 | }
87 | }
88 |
89 | public override void Redraw(float currentTime, float elapsedTime)
90 | {
91 | // selected vehicle (user can mouse click to select another)
92 | IVehicle selected = Demo.SelectedVehicle;
93 |
94 | Demo.UpdateCamera(elapsedTime, selected);
95 | Demo.GridUtility(Vector3.Zero);
96 |
97 | //Draw flow field
98 | const float RANGE = 50;
99 | const int SAMPLES = 25;
100 | for (int i = 0; i < SAMPLES; i++)
101 | {
102 | for (int j = 0; j < SAMPLES; j++)
103 | {
104 | Vector3 location = new Vector3(RANGE / SAMPLES * i - RANGE / 2, 0, RANGE / SAMPLES * j - RANGE / 2);
105 | var flow = FlowField.Sample(location);
106 | Annotations.Line(location, location + flow, Color.Black.ToVector3().FromXna());
107 | }
108 | }
109 |
110 | // draw vehicles
111 | foreach (var vehicle in _followers)
112 | vehicle.Draw();
113 | }
114 |
115 | public override void Close()
116 | {
117 | _followers.Clear();
118 | }
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/Demo/PlugIns/GatewayPathFollowing/GatewayPathFollowingPlugin.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Demo.PlugIns.MeshPathFollowing;
5 | using Microsoft.Xna.Framework;
6 | using SharpSteer2;
7 | using SharpSteer2.Helpers;
8 | using SharpSteer2.Pathway;
9 | using Vector3 = System.Numerics.Vector3;
10 |
11 | namespace Demo.PlugIns.GatewayPathFollowing
12 | {
13 | public class GatewayPathFollowingPlugin
14 | :PlugIn
15 | {
16 | private GatewayPathway _path;
17 | private readonly List _walkers = new List();
18 |
19 | public override bool RequestInitialSelection
20 | {
21 | get
22 | {
23 | return true;
24 | }
25 | }
26 |
27 | public GatewayPathFollowingPlugin(IAnnotationService annotations)
28 | :base(annotations)
29 | {
30 | }
31 |
32 | public override void Open()
33 | {
34 | GeneratePath();
35 |
36 | _walkers.Clear();
37 | for (int i = 0; i < 7; i++)
38 | {
39 | _walkers.Add(new PathWalker(_path, Annotations, _walkers)
40 | {
41 | Position = new Vector3(i * 1 * 2, 0, 0),
42 | Forward = new Vector3(0, 0, 1),
43 | });
44 | }
45 | }
46 |
47 | private void GeneratePath()
48 | {
49 | var rand = new Random();
50 |
51 | float xOffsetDeriv = 0;
52 | float xOffset = 0;
53 |
54 | var gateways = new List();
55 | for (var i = 0; i < 200; i++)
56 | {
57 | xOffsetDeriv = Utilities.Clamp((float)rand.NextDouble() * 2 - (xOffsetDeriv * 0.0125f), -15, 15);
58 | xOffset += xOffsetDeriv;
59 |
60 | if (i % 3 == 0)
61 | {
62 | gateways.Add(new GatewayPathway.Gateway(
63 | new Vector3(xOffset + 1, 0, i) * 5,
64 | new Vector3(xOffset - 1, 0, i) * 5
65 | ));
66 | }
67 | else
68 | {
69 | gateways.Add(new GatewayPathway.Gateway(
70 | new Vector3(xOffset - 1, 0, i) * 5,
71 | new Vector3(xOffset + 1, 0, i) * 5
72 | ));
73 | }
74 | }
75 |
76 | _path = new GatewayPathway(gateways);
77 | }
78 |
79 | public override void Update(float currentTime, float elapsedTime)
80 | {
81 | foreach (var walker in _walkers)
82 | walker.Update(elapsedTime);
83 | }
84 |
85 | public override void Redraw(float currentTime, float elapsedTime)
86 | {
87 | Demo.UpdateCamera(elapsedTime, _walkers[0]);
88 | foreach (var walker in _walkers)
89 | walker.Draw();
90 |
91 | var tri = _path.TrianglePathway.Triangles.ToArray();
92 | foreach (var triangle in tri)
93 | {
94 | Drawing.Draw2dLine(triangle.A, triangle.A + triangle.Edge0, Color.Black);
95 | Drawing.Draw2dLine(triangle.A, triangle.A + triangle.Edge1, Color.Black);
96 | Drawing.Draw2dLine(triangle.A + triangle.Edge0, triangle.A + triangle.Edge1, Color.Black);
97 | }
98 |
99 | var points = _path.Centerline.Points.ToArray();
100 | for (int i = 0; i < points.Length - 1; i++)
101 | {
102 | Drawing.Draw2dLine(points[i], points[i + 1], Color.Gray);
103 | }
104 | }
105 |
106 | public override void Close()
107 | {
108 |
109 | }
110 |
111 | public override string Name
112 | {
113 | get { return "Gateway Path Following"; }
114 | }
115 |
116 | public override IEnumerable Vehicles
117 | {
118 | get
119 | {
120 | return _walkers;
121 | }
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/Demo/PlugIns/LowSpeedTurn/LowSpeedTurn.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // Copyright (C) 2007 Michael Coles
5 | // All rights reserved.
6 | //
7 | // This software is licensed as described in the file license.txt, which
8 | // you should have received as part of this distribution. The terms
9 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
10 |
11 | using Microsoft.Xna.Framework;
12 | using SharpSteer2;
13 | using Vector3 = System.Numerics.Vector3;
14 |
15 | namespace Demo.PlugIns.LowSpeedTurn
16 | {
17 | public class LowSpeedTurn : SimpleVehicle
18 | {
19 | Trail _trail;
20 |
21 | public override float MaxForce { get { return 0.3f; } }
22 | public override float MaxSpeed { get { return 1.5f; } }
23 |
24 | // constructor
25 | public LowSpeedTurn(IAnnotationService annotations = null)
26 | :base(annotations)
27 | {
28 | Reset();
29 | }
30 |
31 | // reset state
32 | public override void Reset()
33 | {
34 | // reset vehicle state
35 | base.Reset();
36 |
37 | // speed along Forward direction.
38 | Speed = _startSpeed;
39 |
40 | // initial position along X axis
41 | Position = new Vector3(_startX, 0, 0);
42 |
43 | // for next instance: step starting location
44 | _startX += 2;
45 |
46 | // for next instance: step speed
47 | _startSpeed += 0.15f;
48 |
49 | // 15 seconds and 150 points along the trail
50 | _trail = new Trail(15, 150);
51 | }
52 |
53 | // draw into the scene
54 | public void Draw()
55 | {
56 | Drawing.DrawBasic2dCircularVehicle(this, Color.Gray);
57 | _trail.Draw(annotation);
58 | }
59 |
60 | // per frame simulation update
61 | public void Update(float currentTime, float elapsedTime)
62 | {
63 | ApplySteeringForce(Steering, elapsedTime);
64 |
65 | // annotation
66 | annotation.VelocityAcceleration(this);
67 | _trail.Record(currentTime, Position);
68 | }
69 |
70 | // reset starting positions
71 | public static void ResetStarts()
72 | {
73 | _startX = 0;
74 | _startSpeed = 0;
75 | }
76 |
77 | // constant steering force
78 | private static Vector3 Steering
79 | {
80 | get { return new Vector3(1, 0, -1); }
81 | }
82 |
83 | // for stepping the starting conditions for next vehicle
84 | static float _startX;
85 | static float _startSpeed;
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/Demo/PlugIns/LowSpeedTurn/LowSpeedTurnPlugIn.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // Copyright (C) 2007 Michael Coles
5 | // All rights reserved.
6 | //
7 | // This software is licensed as described in the file license.txt, which
8 | // you should have received as part of this distribution. The terms
9 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
10 |
11 | using System;
12 | using System.Collections.Generic;
13 | using Microsoft.Xna.Framework;
14 | using SharpSteer2;
15 | using Vector3 = System.Numerics.Vector3;
16 |
17 | namespace Demo.PlugIns.LowSpeedTurn
18 | {
19 | class LowSpeedTurnPlugIn : PlugIn
20 | {
21 | const int LST_COUNT = 5;
22 | const float LST_LOOK_DOWN_DISTANCE = 18;
23 | static readonly Vector3 _lstViewCenter = new Vector3(7, 0, -2);
24 | static readonly Vector3 _lstPlusZ = new Vector3(0, 0, 1);
25 |
26 | public LowSpeedTurnPlugIn(IAnnotationService annotations)
27 | :base(annotations)
28 | {
29 | _all = new List();
30 | }
31 |
32 | public override String Name { get { return "Low Speed Turn"; } }
33 |
34 | public override float SelectionOrderSortKey { get { return 0.05f; } }
35 |
36 | public override void Open()
37 | {
38 | // create a given number of agents with stepped inital parameters,
39 | // store pointers to them in an array.
40 | LowSpeedTurn.ResetStarts();
41 | for (int i = 0; i < LST_COUNT; i++)
42 | _all.Add(new LowSpeedTurn(Annotations));
43 |
44 | // initial selected vehicle
45 | Demo.SelectedVehicle = _all[0];
46 |
47 | // initialize camera
48 | Demo.Camera.Mode = Camera.CameraMode.Fixed;
49 | Demo.Camera.FixedUp = _lstPlusZ;
50 | Demo.Camera.FixedTarget = _lstViewCenter;
51 | Demo.Camera.FixedPosition = _lstViewCenter;
52 | Demo.Camera.FixedPosition.Y += LST_LOOK_DOWN_DISTANCE;
53 | Demo.Camera.LookDownDistance = LST_LOOK_DOWN_DISTANCE;
54 | Demo.Camera.FixedDistanceVerticalOffset = Demo.CAMERA2_D_ELEVATION;
55 | Demo.Camera.FixedDistanceDistance = Demo.CAMERA_TARGET_DISTANCE;
56 | }
57 |
58 | public override void Update(float currentTime, float elapsedTime)
59 | {
60 | // update, draw and annotate each agent
61 | foreach (LowSpeedTurn t in _all)
62 | t.Update(currentTime, elapsedTime);
63 | }
64 |
65 | public override void Redraw(float currentTime, float elapsedTime)
66 | {
67 | // selected vehicle (user can mouse click to select another)
68 | IVehicle selected = Demo.SelectedVehicle;
69 |
70 | // vehicle nearest mouse (to be highlighted)
71 | IVehicle nearMouse = Demo.VehicleNearestToMouse();
72 |
73 | // update camera
74 | Demo.UpdateCamera(elapsedTime, selected);
75 |
76 | // draw "ground plane"
77 | Demo.GridUtility(selected.Position);
78 |
79 | // update, draw and annotate each agent
80 | foreach (LowSpeedTurn agent in _all)
81 | {
82 | agent.Draw();
83 |
84 | // display speed near agent's screen position
85 | Color textColor = new Color(new Vector3(0.8f, 0.8f, 1.0f).ToXna());
86 | Vector3 textOffset = new Vector3(0, 0.25f, 0);
87 | Vector3 textPosition = agent.Position + textOffset;
88 | String annote = String.Format("{0:0.00}", agent.Speed);
89 | Drawing.Draw2dTextAt3dLocation(annote, textPosition, textColor);
90 | }
91 |
92 | // highlight vehicle nearest mouse
93 | Demo.HighlightVehicleUtility(nearMouse);
94 | }
95 |
96 | public override void Close()
97 | {
98 | _all.Clear();
99 | }
100 |
101 | public override void Reset()
102 | {
103 | // reset each agent
104 | LowSpeedTurn.ResetStarts();
105 | foreach (LowSpeedTurn t in _all)
106 | t.Reset();
107 | }
108 |
109 | public override IEnumerable Vehicles
110 | {
111 | get { return _all.ConvertAll(v => (IVehicle) v); }
112 | }
113 |
114 | readonly List _all; // for allVehicles
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/Demo/PlugIns/MapDrive/GCRoute.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // Copyright (C) 2007 Michael Coles
5 | // All rights reserved.
6 | //
7 | // This software is licensed as described in the file license.txt, which
8 | // you should have received as part of this distribution. The terms
9 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
10 |
11 | using System;
12 | using System.Collections.Generic;
13 | using System.Numerics;
14 |
15 | namespace Demo.PlugIns.MapDrive
16 | {
17 | // A variation on PolylinePathway (whose path tube radius is constant)
18 | // GCRoute (Grand Challenge Route) has an array of radii-per-segment
19 | //
20 | // XXX The OpenSteer path classes are long overdue for a rewrite. When
21 | // XXX that happens, support should be provided for constant-radius,
22 | // XXX radius-per-segment (as in GCRoute), and radius-per-vertex.
23 | public class GCRoute : PolylinePathway
24 | {
25 | // construct a GCRoute given the number of points (vertices), an
26 | // array of points, an array of per-segment path radii, and a flag
27 | // indiating if the path is connected at the end.
28 | public GCRoute(Vector3[] points, IList radii, bool cyclic)
29 | {
30 | Initialize(points, radii[0], cyclic);
31 |
32 | Radii = new float[PointCount];
33 |
34 | // loop over all points
35 | for (int i = 0; i < PointCount; i++)
36 | {
37 | // copy in point locations, closing cycle when appropriate
38 | bool closeCycle = Cyclic && (i == PointCount - 1);
39 | int j = closeCycle ? 0 : i;
40 | Points[i] = points[j];
41 | Radii[i] = radii[i];
42 | }
43 | }
44 |
45 | // override the PolylinePathway method to allow for GCRoute-style
46 | // per-leg radii
47 |
48 | // Given an arbitrary point ("A"), returns the nearest point ("P") on
49 | // this path. Also returns, via output arguments, the path tangent at
50 | // P and a measure of how far A is outside the Pathway's "tube". Note
51 | // that a negative distance indicates A is inside the Pathway.
52 | public override Vector3 MapPointToPath(Vector3 point, out Vector3 tangent, out float outside)
53 | {
54 | Vector3 onPath = Vector3.Zero;
55 | tangent = Vector3.Zero;
56 | outside = float.MaxValue;
57 |
58 | // loop over all segments, find the one nearest to the given point
59 | for (int i = 1; i < PointCount; i++)
60 | {
61 | Vector3 chosen;
62 | float d = PointToSegmentDistance(point, Points[i - 1], Points[i], Tangents[i], Lengths[i], out chosen);
63 |
64 | // measure how far original point is outside the Pathway's "tube"
65 | // (negative values (from 0 to -radius) measure "insideness")
66 | float o = d - Radii[i];
67 |
68 | // when this is the smallest "outsideness" seen so far, take
69 | // note and save the corresponding point-on-path and tangent
70 | if (o < outside)
71 | {
72 | outside = o;
73 | onPath = chosen;
74 | tangent = Tangents[i];
75 | }
76 | }
77 |
78 | // return point on path
79 | return onPath;
80 | }
81 |
82 | // ignore that "tangent" output argument which is never used
83 | // XXX eventually move this to Pathway class
84 | public Vector3 MapPointToPath(Vector3 point, out float outside)
85 | {
86 | Vector3 tangent;
87 | return MapPointToPath(point, out tangent, out outside);
88 | }
89 |
90 | // get the index number of the path segment nearest the given point
91 | // XXX consider moving this to path class
92 | public int IndexOfNearestSegment(Vector3 point)
93 | {
94 | int index = 0;
95 | float minDistance = float.MaxValue;
96 |
97 | // loop over all segments, find the one nearest the given point
98 | for (int i = 1; i < PointCount; i++)
99 | {
100 | Vector3 chosen;
101 | float d = PointToSegmentDistance(point, Points[i - 1], Points[i], Tangents[i], Lengths[i], out chosen);
102 | if (d < minDistance)
103 | {
104 | minDistance = d;
105 | index = i;
106 | }
107 | }
108 | return index;
109 | }
110 |
111 | // returns the dot product of the tangents of two path segments,
112 | // used to measure the "angle" at a path vertex: how sharp is the turn?
113 | public float DotSegmentUnitTangents(int segmentIndex0, int segmentIndex1)
114 | {
115 | return Vector3.Dot(Tangents[segmentIndex0], Tangents[segmentIndex1]);
116 | }
117 |
118 | // return path tangent at given point (its projection on path)
119 | public Vector3 TangentAt(Vector3 point)
120 | {
121 | return Tangents[IndexOfNearestSegment(point)];
122 | }
123 |
124 | // return path tangent at given point (its projection on path),
125 | // multiplied by the given pathfollowing direction (+1/-1 =
126 | // upstream/downstream). Near path vertices (waypoints) use the
127 | // tangent of the "next segment" in the given direction
128 | public Vector3 TangentAt(Vector3 point, int pathFollowDirection)
129 | {
130 | int segmentIndex = IndexOfNearestSegment(point);
131 | int nextIndex = segmentIndex + pathFollowDirection;
132 | bool insideNextSegment = IsInsidePathSegment(point, nextIndex);
133 | int i = (segmentIndex + (insideNextSegment ? pathFollowDirection : 0));
134 | return Tangents[i] * pathFollowDirection;
135 | }
136 |
137 | // is the given point "near" a waypoint of this path? ("near" == closer
138 | // to the waypoint than the max of radii of two adjacent segments)
139 | public bool NearWaypoint(Vector3 point)
140 | {
141 | // loop over all waypoints
142 | for (int i = 1; i < PointCount; i++)
143 | {
144 | // return true if near enough to this waypoint
145 | float r = Math.Max(Radii[i], Radii[(i + 1) % PointCount]);
146 | float d = (point - Points[i]).Length();
147 | if (d < r) return true;
148 | }
149 | return false;
150 | }
151 |
152 | // is the given point inside the path tube of the given segment
153 | // number? (currently not used. this seemed like a useful utility,
154 | // but wasn't right for the problem I was trying to solve)
155 | private bool IsInsidePathSegment(Vector3 point, int segmentIndex)
156 | {
157 | if (segmentIndex < 1 || segmentIndex >= PointCount) return false;
158 |
159 | int i = segmentIndex;
160 |
161 | Vector3 chosen;
162 | float d = PointToSegmentDistance(point, Points[i - 1], Points[i], Tangents[i], Lengths[i], out chosen);
163 |
164 | // measure how far original point is outside the Pathway's "tube"
165 | // (negative values (from 0 to -radius) measure "insideness")
166 | float o = d - Radii[i];
167 |
168 | // return true if point is inside the tube
169 | return o < 0;
170 | }
171 |
172 | // per-segment radius (width) array
173 | public readonly float[] Radii;
174 | }
175 | }
176 |
--------------------------------------------------------------------------------
/Demo/PlugIns/MapDrive/TerrainMap.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // Copyright (C) 2007 Michael Coles
5 | // All rights reserved.
6 | //
7 | // This software is licensed as described in the file license.txt, which
8 | // you should have received as part of this distribution. The terms
9 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
10 |
11 | using System;
12 | using Microsoft.Xna.Framework;
13 | using SharpSteer2;
14 | using SharpSteer2.Helpers;
15 | using Vector3 = System.Numerics.Vector3;
16 |
17 | namespace Demo.PlugIns.MapDrive
18 | {
19 | public class TerrainMap
20 | {
21 | public TerrainMap(Vector3 c, float x, float z, int r)
22 | {
23 | Center = c;
24 | XSize = x;
25 | ZSize = z;
26 | Resolution = r;
27 | _outsideValue = false;
28 |
29 | _map = new bool[Resolution * Resolution];
30 | for (int i = 0; i < Resolution * Resolution; i++)
31 | {
32 | _map[i] = false;
33 | }
34 | }
35 |
36 | // clear the map (to false)
37 | public void Clear()
38 | {
39 | for (int i = 0; i < Resolution; i++)
40 | for (int j = 0; j < Resolution; j++)
41 | SetMapBit(i, j, false);
42 | }
43 |
44 | // get and set a bit based on 2d integer map index
45 | public bool GetMapBit(int i, int j)
46 | {
47 | return _map[MapAddress(i, j)];
48 | }
49 |
50 | public void SetMapBit(int i, int j, bool value)
51 | {
52 | _map[MapAddress(i, j)] = value;
53 | }
54 |
55 | // get a value based on a position in 3d world space
56 | private bool GetMapValue(Vector3 point)
57 | {
58 | Vector3 local = point - Center;
59 | local.Y = 0;
60 | Vector3 localXZ = local;
61 |
62 | float hxs = XSize / 2;
63 | float hzs = ZSize / 2;
64 |
65 | float x = localXZ.X;
66 | float z = localXZ.Z;
67 |
68 | bool isOut = (x > +hxs) || (x < -hxs) || (z > +hzs) || (z < -hzs);
69 |
70 | if (isOut)
71 | {
72 | return _outsideValue;
73 | }
74 | else
75 | {
76 | int i = (int)Utilities.RemapInterval(x, -hxs, hxs, 0.0f, Resolution);
77 | int j = (int)Utilities.RemapInterval(z, -hzs, hzs, 0.0f, Resolution);
78 | return GetMapBit(i, j);
79 | }
80 | }
81 |
82 | public void xxxDrawMap()
83 | {
84 | float xs = XSize / Resolution;
85 | float zs = ZSize / Resolution;
86 | Vector3 alongRow = new Vector3(xs, 0, 0);
87 | Vector3 nextRow = new Vector3(-XSize, 0, zs);
88 | Vector3 g = new Vector3((XSize - xs) / -2, 0, (ZSize - zs) / -2);
89 | g += Center;
90 | for (int j = 0; j < Resolution; j++)
91 | {
92 | for (int i = 0; i < Resolution; i++)
93 | {
94 | if (GetMapBit(i, j))
95 | {
96 | // spikes
97 | // Vector3 spikeTop (0, 5.0f, 0);
98 | // drawLine (g, g+spikeTop, gWhite);
99 |
100 | // squares
101 | const float ROCK_HEIGHT = 0;
102 | Vector3 v1 = new Vector3(+xs / 2, ROCK_HEIGHT, +zs / 2);
103 | Vector3 v2 = new Vector3(+xs / 2, ROCK_HEIGHT, -zs / 2);
104 | Vector3 v3 = new Vector3(-xs / 2, ROCK_HEIGHT, -zs / 2);
105 | Vector3 v4 = new Vector3(-xs / 2, ROCK_HEIGHT, +zs / 2);
106 | // Vector3 redRockColor (0.6f, 0.1f, 0.0f);
107 | Color orangeRockColor = new Color((byte)(255.0f * 0.5f), (byte)(255.0f * 0.2f), (byte)(255.0f * 0.0f));
108 | Drawing.DrawQuadrangle(g + v1, g + v2, g + v3, g + v4, orangeRockColor);
109 |
110 | // pyramids
111 | // Vector3 top (0, xs/2, 0);
112 | // Vector3 redRockColor (0.6f, 0.1f, 0.0f);
113 | // Vector3 orangeRockColor (0.5f, 0.2f, 0.0f);
114 | // drawTriangle (g+v1, g+v2, g+top, redRockColor);
115 | // drawTriangle (g+v2, g+v3, g+top, orangeRockColor);
116 | // drawTriangle (g+v3, g+v4, g+top, redRockColor);
117 | // drawTriangle (g+v4, g+v1, g+top, orangeRockColor);
118 | }
119 | g += alongRow;
120 | }
121 | g += nextRow;
122 | }
123 | }
124 |
125 | public float MinSpacing()
126 | {
127 | return Math.Min(XSize, ZSize) / Resolution;
128 | }
129 |
130 | // used to detect if vehicle body is on any obstacles
131 | public bool ScanLocalXZRectangle(ILocalSpaceBasis localSpace, float xMin, float xMax, float zMin, float zMax)
132 | {
133 | float spacing = MinSpacing() / 2;
134 |
135 | for (float x = xMin; x < xMax; x += spacing)
136 | {
137 | for (float z = zMin; z < zMax; z += spacing)
138 | {
139 | Vector3 sample = new Vector3(x, 0, z);
140 | Vector3 global = localSpace.GlobalizePosition(sample);
141 | if (GetMapValue(global)) return true;
142 | }
143 | }
144 | return false;
145 | }
146 |
147 | // Scans along a ray (directed line segment) on the XZ plane, sampling
148 | // the map for a "true" cell. Returns the index of the first sample
149 | // that gets a "hit", or zero if no hits found.
150 | public int ScanXZray(Vector3 origin, Vector3 sampleSpacing, int sampleCount)
151 | {
152 | Vector3 samplePoint = origin;
153 |
154 | for (int i = 1; i <= sampleCount; i++)
155 | {
156 | samplePoint += sampleSpacing;
157 | if (GetMapValue(samplePoint)) return i;
158 | }
159 |
160 | return 0;
161 | }
162 |
163 | public int Cellwidth() { return Resolution; } // xxx cwr
164 | public int Cellheight() { return Resolution; } // xxx cwr
165 | public bool IsPassable(Vector3 point) { return !GetMapValue(point); }
166 |
167 |
168 | public Vector3 Center;
169 | public readonly float XSize;
170 | public readonly float ZSize;
171 | public readonly int Resolution;
172 |
173 | private readonly bool _outsideValue;
174 |
175 | int MapAddress(int i, int j) { return i + (j * Resolution); }
176 |
177 | readonly bool[] _map;
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/Demo/PlugIns/MeshPathFollowing/MeshPathFollowingPlugin.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Microsoft.Xna.Framework;
5 | using SharpSteer2;
6 | using SharpSteer2.Pathway;
7 | using Vector3 = System.Numerics.Vector3;
8 |
9 | namespace Demo.PlugIns.MeshPathFollowing
10 | {
11 | public class MeshPathFollowingPlugin
12 | :PlugIn
13 | {
14 | private TrianglePathway _path;
15 | private readonly List _walkers = new List();
16 |
17 | public override bool RequestInitialSelection
18 | {
19 | get
20 | {
21 | return true;
22 | }
23 | }
24 |
25 | public MeshPathFollowingPlugin(IAnnotationService annotations)
26 | :base(annotations)
27 | {
28 | }
29 |
30 | public override void Open()
31 | {
32 | GeneratePath();
33 |
34 | _walkers.Clear();
35 | for (int i = 0; i < 7; i++)
36 | {
37 | _walkers.Add(new PathWalker(_path, Annotations, _walkers)
38 | {
39 | Position = new Vector3(i * 1 * 2, 0, 0),
40 | Forward = new Vector3(0, 0, 1)
41 | });
42 | }
43 | }
44 |
45 | private void GeneratePath()
46 | {
47 | var rand = new Random();
48 |
49 | float xOffsetDeriv = 0;
50 | float xOffset = 0;
51 |
52 | var points = new List();
53 | for (var i = 0; i < 200; i++)
54 | {
55 | xOffsetDeriv = MathHelper.Clamp((float)rand.NextDouble() * 2 - (xOffsetDeriv * 0.0125f), -15, 15);
56 | xOffset += xOffsetDeriv;
57 |
58 | points.Add(new Vector3(xOffset + 1, 0, i) * 5);
59 | points.Add(new Vector3(xOffset - 1, 0, i) * 5);
60 | }
61 |
62 | _path = new TrianglePathway(Enumerable.Range(0, points.Count - 2).Select(i => new TrianglePathway.Triangle(points[i], points[i + 1], points[i + 2])));
63 | }
64 |
65 | public override void Update(float currentTime, float elapsedTime)
66 | {
67 | foreach (var walker in _walkers)
68 | walker.Update(elapsedTime);
69 | }
70 |
71 | public override void Redraw(float currentTime, float elapsedTime)
72 | {
73 | Demo.UpdateCamera(elapsedTime, _walkers[0]);
74 | foreach (var walker in _walkers)
75 | walker.Draw();
76 |
77 | var tri = _path.Triangles.ToArray();
78 | foreach (var triangle in tri)
79 | {
80 | Drawing.Draw2dLine(triangle.A, triangle.A + triangle.Edge0, Color.Black);
81 | Drawing.Draw2dLine(triangle.A, triangle.A + triangle.Edge1, Color.Black);
82 | Drawing.Draw2dLine(triangle.A + triangle.Edge0, triangle.A + triangle.Edge1, Color.Black);
83 | }
84 |
85 | var points = _path.Centerline.Points.ToArray();
86 | for (int i = 0; i < points.Length - 1; i++)
87 | {
88 | Drawing.Draw2dLine(points[i], points[i + 1], Color.Gray);
89 | }
90 | }
91 |
92 | public override void Close()
93 | {
94 |
95 | }
96 |
97 | public override string Name
98 | {
99 | get { return "Nav Mesh Path Following"; }
100 | }
101 |
102 | public override IEnumerable Vehicles
103 | {
104 | get
105 | {
106 | return _walkers;
107 | }
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/Demo/PlugIns/MeshPathFollowing/PathWalker.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using Microsoft.Xna.Framework;
4 | using SharpSteer2;
5 | using SharpSteer2.Helpers;
6 | using SharpSteer2.Pathway;
7 | using Vector3 = System.Numerics.Vector3;
8 |
9 | namespace Demo.PlugIns.MeshPathFollowing
10 | {
11 | public class PathWalker
12 | :SimpleVehicle
13 | {
14 | public readonly IPathway Path;
15 | private readonly List _vehicles;
16 |
17 | public override float MaxForce { get { return 1; } }
18 | public override float MaxSpeed { get { return 10; } }
19 |
20 | private readonly Trail _trail = new Trail(30, 300);
21 |
22 | public PathWalker(IPathway path, IAnnotationService annotation, List vehicles)
23 | :base(annotation)
24 | {
25 | Path = path;
26 | _vehicles = vehicles;
27 | }
28 |
29 | private float _time;
30 | public void Update(float dt)
31 | {
32 | const float PREDICTION = 3;
33 |
34 | //Avoid other vehicles, and follow the path
35 | var avoid = SteerToAvoidCloseNeighbors(0.25f, _vehicles.Except(new[] { this }));
36 | if (avoid != Vector3.Zero)
37 | ApplySteeringForce(avoid, dt);
38 | else
39 | {
40 | var f = SteerToFollowPath(true, PREDICTION, Path);
41 | ApplySteeringForce(f, dt);
42 | }
43 |
44 | //If the vehicle leaves the path, penalise it by applying a braking force
45 | if (Path.HowFarOutsidePath(Position) > 0)
46 | ApplyBrakingForce(0.3f, dt);
47 |
48 | _time += dt;
49 | _trail.Record(_time, Position);
50 |
51 | annotation.VelocityAcceleration(this);
52 | }
53 |
54 | internal void Draw()
55 | {
56 | Drawing.DrawBasic2dCircularVehicle(this, Color.Gray);
57 |
58 | _trail.Draw(annotation);
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/Demo/PlugIns/MultiplePursuit/MpBase.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // All rights reserved.
5 | //
6 | // This software is licensed as described in the file license.txt, which
7 | // you should have received as part of this distribution. The terms
8 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
9 |
10 | using Microsoft.Xna.Framework;
11 | using SharpSteer2;
12 |
13 | namespace Demo.PlugIns.MultiplePursuit
14 | {
15 | public class MpBase : SimpleVehicle
16 | {
17 | protected Trail Trail;
18 |
19 | public override float MaxForce { get { return 5; } }
20 | public override float MaxSpeed { get { return 3; } }
21 |
22 | // constructor
23 | protected MpBase(IAnnotationService annotations = null)
24 | :base(annotations)
25 | {
26 | Reset();
27 | }
28 |
29 | // reset state
30 | public override void Reset()
31 | {
32 | base.Reset(); // reset the vehicle
33 |
34 | Speed = 0; // speed along Forward direction.
35 | Trail = new Trail();
36 | Trail.Clear(); // prevent long streaks due to teleportation
37 | }
38 |
39 | // draw into the scene
40 | public void Draw()
41 | {
42 | Drawing.DrawBasic2dCircularVehicle(this, BodyColor);
43 | Trail.Draw(annotation);
44 | }
45 |
46 | // for draw method
47 | protected Color BodyColor;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Demo/PlugIns/MultiplePursuit/MpPlugIn.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // All rights reserved.
5 | //
6 | // This software is licensed as described in the file license.txt, which
7 | // you should have received as part of this distribution. The terms
8 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
9 |
10 | using System;
11 | using System.Collections.Generic;
12 | using SharpSteer2;
13 |
14 | namespace Demo.PlugIns.MultiplePursuit
15 | {
16 | public class MpPlugIn : PlugIn
17 | {
18 | public MpPlugIn(IAnnotationService annotations)
19 | :base(annotations)
20 | {
21 | _allMp = new List();
22 | }
23 |
24 | public override String Name { get { return "Multiple Pursuit"; } }
25 |
26 | public override float SelectionOrderSortKey { get { return 0.04f; } }
27 |
28 | public override void Open()
29 | {
30 | // create the wanderer, saving a pointer to it
31 | _wanderer = new MpWanderer(Annotations);
32 | _allMp.Add(_wanderer);
33 |
34 | // create the specified number of pursuers, save pointers to them
35 | const int PURSUER_COUNT = 30;
36 | for (int i = 0; i < PURSUER_COUNT; i++)
37 | _allMp.Add(new MpPursuer(_wanderer, Annotations));
38 | //pBegin = allMP.begin() + 1; // iterator pointing to first pursuer
39 | //pEnd = allMP.end(); // iterator pointing to last pursuer
40 |
41 | // initialize camera
42 | Demo.SelectedVehicle = _wanderer;
43 | Demo.Camera.Mode = Camera.CameraMode.StraightDown;
44 | Demo.Camera.FixedDistanceDistance = Demo.CAMERA_TARGET_DISTANCE;
45 | Demo.Camera.FixedDistanceVerticalOffset = Demo.CAMERA2_D_ELEVATION;
46 | }
47 |
48 | public override void Update(float currentTime, float elapsedTime)
49 | {
50 | // update the wanderer
51 | _wanderer.Update(currentTime, elapsedTime);
52 |
53 | // update each pursuer
54 | for (int i = 1; i < _allMp.Count; i++)
55 | {
56 | ((MpPursuer)_allMp[i]).Update(currentTime, elapsedTime);
57 | }
58 | }
59 |
60 | public override void Redraw(float currentTime, float elapsedTime)
61 | {
62 | // selected vehicle (user can mouse click to select another)
63 | IVehicle selected = Demo.SelectedVehicle;
64 |
65 | // vehicle nearest mouse (to be highlighted)
66 | IVehicle nearMouse = Demo.VehicleNearestToMouse();
67 |
68 | // update camera
69 | Demo.UpdateCamera(elapsedTime, selected);
70 |
71 | // draw "ground plane"
72 | Demo.GridUtility(selected.Position);
73 |
74 | // draw each vehicles
75 | foreach (MpBase mp in _allMp)
76 | mp.Draw();
77 |
78 | // highlight vehicle nearest mouse
79 | Demo.HighlightVehicleUtility(nearMouse);
80 | Demo.CircleHighlightVehicleUtility(selected);
81 | }
82 |
83 | public override void Close()
84 | {
85 | // delete wanderer, all pursuers, and clear list
86 | _allMp.Clear();
87 | }
88 |
89 | public override void Reset()
90 | {
91 | // reset wanderer and pursuers
92 | _wanderer.Reset();
93 | for (int i = 1; i < _allMp.Count; i++) _allMp[i].Reset();
94 |
95 | // immediately jump to default camera position
96 | Demo.Camera.DoNotSmoothNextMove();
97 | Demo.Camera.ResetLocalSpace();
98 | }
99 |
100 | //const AVGroup& allVehicles () {return (const AVGroup&) allMP;}
101 | public override IEnumerable Vehicles
102 | {
103 | get { return _allMp.ConvertAll(m => (IVehicle) m); }
104 | }
105 |
106 | // a group (STL vector) of all vehicles
107 | readonly List _allMp;
108 |
109 | MpWanderer _wanderer;
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/Demo/PlugIns/MultiplePursuit/MpPursuer.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // Copyright (C) 2007 Michael Coles
5 | // All rights reserved.
6 | //
7 | // This software is licensed as described in the file license.txt, which
8 | // you should have received as part of this distribution. The terms
9 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
10 |
11 | using Microsoft.Xna.Framework;
12 | using SharpSteer2;
13 | using SharpSteer2.Helpers;
14 | using Vector3 = System.Numerics.Vector3;
15 |
16 | namespace Demo.PlugIns.MultiplePursuit
17 | {
18 | public class MpPursuer : MpBase
19 | {
20 | // constructor
21 | public MpPursuer(MpWanderer w, IAnnotationService annotations = null)
22 | :base(annotations)
23 | {
24 | _wanderer = w;
25 | Reset();
26 | }
27 |
28 | // reset state
29 | public override void Reset()
30 | {
31 | base.Reset();
32 | BodyColor = new Color((byte)(255.0f * 0.6f), (byte)(255.0f * 0.4f), (byte)(255.0f * 0.4f)); // redish
33 | if(_wanderer != null) RandomizeStartingPositionAndHeading();
34 | }
35 |
36 | // one simulation step
37 | public void Update(float currentTime, float elapsedTime)
38 | {
39 | // when pursuer touches quarry ("wanderer"), reset its position
40 | float d = Vector3.Distance(Position, _wanderer.Position);
41 | float r = Radius + _wanderer.Radius;
42 | if (d < r) Reset();
43 |
44 | const float MAX_TIME = 20; // xxx hard-to-justify value
45 | ApplySteeringForce(SteerForPursuit(_wanderer, MAX_TIME), elapsedTime);
46 |
47 | // for annotation
48 | Trail.Record(currentTime, Position);
49 | }
50 |
51 | // reset position
52 | private void RandomizeStartingPositionAndHeading()
53 | {
54 | // randomize position on a ring between inner and outer radii
55 | // centered around the home base
56 | const float INNER = 20;
57 | const float OUTER = 30;
58 | float radius = RandomHelpers.Random(INNER, OUTER);
59 | Vector3 randomOnRing = Vector3Helpers.RandomUnitVectorOnXZPlane() * radius;
60 | Position = (_wanderer.Position + randomOnRing);
61 |
62 | // randomize 2D heading
63 | RandomizeHeadingOnXZPlane();
64 | }
65 |
66 | readonly MpWanderer _wanderer;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/Demo/PlugIns/MultiplePursuit/MpWanderer.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // Copyright (C) 2007 Michael Coles
5 | // All rights reserved.
6 | //
7 | // This software is licensed as described in the file license.txt, which
8 | // you should have received as part of this distribution. The terms
9 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
10 |
11 | using Microsoft.Xna.Framework;
12 | using SharpSteer2;
13 | using Vector3 = System.Numerics.Vector3;
14 |
15 | namespace Demo.PlugIns.MultiplePursuit
16 | {
17 | public class MpWanderer : MpBase
18 | {
19 | // constructor
20 | public MpWanderer(IAnnotationService annotations = null)
21 | :base(annotations)
22 | {
23 | Reset();
24 | }
25 |
26 | // reset state
27 | public override void Reset()
28 | {
29 | base.Reset();
30 | BodyColor = new Color((byte)(255.0f * 0.4f), (byte)(255.0f * 0.6f), (byte)(255.0f * 0.4f)); // greenish
31 | }
32 |
33 | // one simulation step
34 | public void Update(float currentTime, float elapsedTime)
35 | {
36 | Vector3 wander2D = SteerForWander(elapsedTime);
37 | wander2D.Y = 0;
38 |
39 | Vector3 steer = Forward + (wander2D * 3);
40 | ApplySteeringForce(steer, elapsedTime);
41 |
42 | // for annotation
43 | Trail.Record(currentTime, Position);
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Demo/PlugIns/OneTurning/OneTurning.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // Copyright (C) 2007 Michael Coles
5 | // All rights reserved.
6 | //
7 | // This software is licensed as described in the file license.txt, which
8 | // you should have received as part of this distribution. The terms
9 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
10 |
11 | using Microsoft.Xna.Framework;
12 | using SharpSteer2;
13 | using Vector3 = System.Numerics.Vector3;
14 |
15 | namespace Demo.PlugIns.OneTurning
16 | {
17 | public class OneTurning : SimpleVehicle
18 | {
19 | Trail _trail;
20 |
21 | public override float MaxForce { get { return 0.3f; } }
22 | public override float MaxSpeed { get { return 5; } }
23 |
24 | // constructor
25 | public OneTurning(IAnnotationService annotations = null)
26 | :base(annotations)
27 | {
28 | Reset();
29 | }
30 |
31 | // reset state
32 | public override void Reset()
33 | {
34 | base.Reset(); // reset the vehicle
35 | Speed = 1.5f; // speed along Forward direction.
36 | _trail = new Trail();
37 | _trail.Clear(); // prevent long streaks due to teleportation
38 | }
39 |
40 | // per frame simulation update
41 | public void Update(float currentTime, float elapsedTime)
42 | {
43 | ApplySteeringForce(new Vector3(-2, 0, -3), elapsedTime);
44 | annotation.VelocityAcceleration(this);
45 | _trail.Record(currentTime, Position);
46 | }
47 |
48 | // draw this character/vehicle into the scene
49 | public void Draw()
50 | {
51 | Drawing.DrawBasic2dCircularVehicle(this, Color.Gray);
52 | _trail.Draw(annotation);
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Demo/PlugIns/OneTurning/OneTurningPlugIn.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // Copyright (C) 2007 Michael Coles
5 | // All rights reserved.
6 | //
7 | // This software is licensed as described in the file license.txt, which
8 | // you should have received as part of this distribution. The terms
9 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
10 |
11 | using System;
12 | using System.Collections.Generic;
13 | using Microsoft.Xna.Framework;
14 | using SharpSteer2;
15 | using Vector3 = System.Numerics.Vector3;
16 |
17 | namespace Demo.PlugIns.OneTurning
18 | {
19 | public class OneTurningPlugIn : PlugIn
20 | {
21 | public OneTurningPlugIn(IAnnotationService annotations)
22 | :base(annotations)
23 | {
24 | _theVehicle = new List();
25 | }
26 |
27 | public override String Name { get { return "One Turning Away"; } }
28 |
29 | public override float SelectionOrderSortKey { get { return 0.06f; } }
30 |
31 | public override void Open()
32 | {
33 | _oneTurning = new OneTurning(Annotations);
34 | Demo.SelectedVehicle = _oneTurning;
35 | _theVehicle.Add(_oneTurning);
36 |
37 | // initialize camera
38 | Demo.Init2dCamera(_oneTurning);
39 | Demo.Camera.Position = new Vector3(10, Demo.CAMERA2_D_ELEVATION, 10);
40 | Demo.Camera.FixedPosition = new Vector3(40);
41 | }
42 |
43 | public override void Update(float currentTime, float elapsedTime)
44 | {
45 | // update simulation of test vehicle
46 | _oneTurning.Update(currentTime, elapsedTime);
47 | }
48 |
49 | public override void Redraw(float currentTime, float elapsedTime)
50 | {
51 | // draw "ground plane"
52 | Demo.GridUtility(_oneTurning.Position);
53 |
54 | // draw test vehicle
55 | _oneTurning.Draw();
56 |
57 | // textual annotation (following the test vehicle's screen position)
58 | String annote = String.Format(" speed: {0:0.00}", _oneTurning.Speed);
59 | Drawing.Draw2dTextAt3dLocation(annote, _oneTurning.Position, Color.Red);
60 | Drawing.Draw2dTextAt3dLocation("start", Vector3.Zero, Color.Green);
61 |
62 | // update camera, tracking test vehicle
63 | Demo.UpdateCamera(elapsedTime, _oneTurning);
64 | }
65 |
66 | public override void Close()
67 | {
68 | _theVehicle.Clear();
69 | _oneTurning = null;
70 | }
71 |
72 | public override void Reset()
73 | {
74 | // reset vehicle
75 | _oneTurning.Reset();
76 | }
77 |
78 | public override IEnumerable Vehicles
79 | {
80 | get { return _theVehicle.ConvertAll(v => (IVehicle) v); }
81 | }
82 |
83 | OneTurning _oneTurning;
84 | readonly List _theVehicle; // for allVehicles
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/Demo/PlugIns/Pedestrian/Globals.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // Copyright (C) 2007 Michael Coles
5 | // All rights reserved.
6 | //
7 | // This software is licensed as described in the file license.txt, which
8 | // you should have received as part of this distribution. The terms
9 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
10 |
11 | using System.Collections.Generic;
12 | using System.Numerics;
13 | using SharpSteer2.Obstacles;
14 |
15 | namespace Demo.PlugIns.Pedestrian
16 | {
17 | class Globals
18 | {
19 | // create path for PlugIn
20 | //
21 | //
22 | // | gap |
23 | //
24 | // f b
25 | // |\ /\ -
26 | // | \ / \ ^
27 | // | \/ \ |
28 | // | /\ \ |
29 | // | / \ c top
30 | // |/ \g / |
31 | // / / |
32 | // /| / V z y=0
33 | // / |______/ - ^
34 | // / e d |
35 | // a/ |
36 | // |<---out-->| o----> x
37 | //
38 | public static PolylinePathway GetTestPath()
39 | {
40 | if (_testPath == null)
41 | {
42 | const float PATH_RADIUS = 2;
43 |
44 | const int PATH_POINT_COUNT = 7;
45 | const float SIZE = 30;
46 | const float TOP = 2 * SIZE;
47 | const float GAP = 1.2f * SIZE;
48 | const float OUTTER = 2 * SIZE;
49 | const float H = 0.5f;
50 | Vector3[] pathPoints = new Vector3[PATH_POINT_COUNT]
51 | {
52 | new Vector3 (H+GAP-OUTTER, 0, H+TOP-OUTTER), // 0 a
53 | new Vector3 (H+GAP, 0, H+TOP), // 1 b
54 | new Vector3 (H+GAP+(TOP/2), 0, H+TOP/2), // 2 c
55 | new Vector3 (H+GAP, 0, H), // 3 d
56 | new Vector3 (H, 0, H), // 4 e
57 | new Vector3 (H, 0, H+TOP), // 5 f
58 | new Vector3 (H+GAP, 0, H+TOP/2) // 6 g
59 | };
60 |
61 | Obstacle1.Center = Vector3.Lerp(pathPoints[0], pathPoints[1], 0.2f);
62 | Obstacle2.Center = Vector3.Lerp(pathPoints[2], pathPoints[3], 0.5f);
63 | Obstacle1.Radius = 3;
64 | Obstacle2.Radius = 5;
65 | Obstacles.Add(Obstacle1);
66 | Obstacles.Add(Obstacle2);
67 |
68 | Endpoint0 = pathPoints[0];
69 | Endpoint1 = pathPoints[PATH_POINT_COUNT - 1];
70 |
71 | _testPath = new PolylinePathway(pathPoints,
72 | PATH_RADIUS,
73 | false);
74 | }
75 | return _testPath;
76 | }
77 |
78 | private static PolylinePathway _testPath = null;
79 | public static readonly SphericalObstacle Obstacle1 = new SphericalObstacle();
80 | public static readonly SphericalObstacle Obstacle2 = new SphericalObstacle();
81 | public static readonly List Obstacles = new List();
82 | public static Vector3 Endpoint0 = Vector3.Zero;
83 | public static Vector3 Endpoint1 = Vector3.Zero;
84 | public static bool UseDirectedPathFollowing = true;
85 |
86 | // this was added for debugging tool, but I might as well leave it in
87 | public static bool WanderSwitch = true;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/Demo/PlugIns/Soccer/AABBox.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // Copyright (C) 2007 Michael Coles
5 | // All rights reserved.
6 | //
7 | // This software is licensed as described in the file license.txt, which
8 | // you should have received as part of this distribution. The terms
9 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
10 |
11 | using Microsoft.Xna.Framework;
12 | using Vector3 = System.Numerics.Vector3;
13 |
14 | namespace Demo.PlugIns.Soccer
15 | {
16 | public class AABBox
17 | {
18 | public AABBox(Vector3 min, Vector3 max)
19 | {
20 | _min = min;
21 | _max = max;
22 | }
23 | public bool IsInsideX(Vector3 p)
24 | {
25 | return !(p.X < _min.X || p.X > _max.X);
26 | }
27 | public bool IsInsideZ(Vector3 p)
28 | {
29 | return !(p.Z < _min.Z || p.Z > _max.Z);
30 | }
31 | public void Draw()
32 | {
33 | Vector3 b = new Vector3(_min.X, 0, _max.Z);
34 | Vector3 c = new Vector3(_max.X, 0, _min.Z);
35 | Color color = new Color(255, 255, 0);
36 | Drawing.DrawLineAlpha(_min, b, color, 1.0f);
37 | Drawing.DrawLineAlpha(b, _max, color, 1.0f);
38 | Drawing.DrawLineAlpha(_max, c, color, 1.0f);
39 | Drawing.DrawLineAlpha(c, _min, color, 1.0f);
40 | }
41 |
42 | Vector3 _min;
43 | Vector3 _max;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Demo/PlugIns/Soccer/Ball.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // Copyright (C) 2007 Michael Coles
5 | // All rights reserved.
6 | //
7 | // This software is licensed as described in the file license.txt, which
8 | // you should have received as part of this distribution. The terms
9 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
10 |
11 | using Microsoft.Xna.Framework;
12 | using SharpSteer2;
13 | using Vector3 = System.Numerics.Vector3;
14 |
15 | namespace Demo.PlugIns.Soccer
16 | {
17 | public class Ball : SimpleVehicle
18 | {
19 | Trail _trail;
20 |
21 | public override float MaxForce { get { return 9; } }
22 | public override float MaxSpeed { get { return 9; } }
23 |
24 | public Ball(AABBox bbox, IAnnotationService annotations = null)
25 | :base(annotations)
26 | {
27 | _mBbox = bbox;
28 | Reset();
29 | }
30 |
31 | // reset state
32 | public override void Reset()
33 | {
34 | base.Reset(); // reset the vehicle
35 | Speed = 0.0f; // speed along Forward direction.
36 |
37 | Position = new Vector3(0, 0, 0);
38 | if (_trail == null) _trail = new Trail(100, 6000);
39 | _trail.Clear(); // prevent long streaks due to teleportation
40 | }
41 |
42 | // per frame simulation update
43 | public void Update(float currentTime, float elapsedTime)
44 | {
45 | ApplyBrakingForce(1.5f, elapsedTime);
46 | ApplySteeringForce(Velocity, elapsedTime);
47 | // are we now outside the field?
48 | if (!_mBbox.IsInsideX(Position))
49 | {
50 | Vector3 d = Velocity;
51 | RegenerateOrthonormalBasis(new Vector3(-d.X, d.Y, d.Z));
52 | ApplySteeringForce(Velocity, elapsedTime);
53 | }
54 | if (!_mBbox.IsInsideZ(Position))
55 | {
56 | Vector3 d = Velocity;
57 | RegenerateOrthonormalBasis(new Vector3(d.X, d.Y, -d.Z));
58 | ApplySteeringForce(Velocity, elapsedTime);
59 | }
60 | _trail.Record(currentTime, Position);
61 | }
62 |
63 | public void Kick(Vector3 dir)
64 | {
65 | Speed = (dir.Length());
66 | RegenerateOrthonormalBasis(dir);
67 | }
68 |
69 | // draw this character/vehicle into the scene
70 | public void Draw()
71 | {
72 | Drawing.DrawBasic2dCircularVehicle(this, Color.Green);
73 | _trail.Draw(annotation);
74 | }
75 |
76 | readonly AABBox _mBbox;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/Demo/PlugIns/Soccer/Globals.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // Copyright (C) 2007 Michael Coles
5 | // All rights reserved.
6 | //
7 | // This software is licensed as described in the file license.txt, which
8 | // you should have received as part of this distribution. The terms
9 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
10 |
11 | using System.Numerics;
12 |
13 | namespace Demo.PlugIns.Soccer
14 | {
15 | class Globals
16 | {
17 | public static readonly Vector3[] PlayerPosition = {
18 | new Vector3(4,0,0),
19 | new Vector3(7,0,-5),
20 | new Vector3(7,0,5),
21 | new Vector3(10,0,-3),
22 | new Vector3(10,0,3),
23 | new Vector3(15,0, -8),
24 | new Vector3(15,0,0),
25 | new Vector3(15,0,8),
26 | new Vector3(4,0,0)
27 | };
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Demo/PlugIns/Soccer/Player.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // Copyright (C) 2007 Michael Coles
5 | // All rights reserved.
6 | //
7 | // This software is licensed as described in the file license.txt, which
8 | // you should have received as part of this distribution. The terms
9 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
10 |
11 | using System.Collections.Generic;
12 | using Microsoft.Xna.Framework;
13 | using SharpSteer2;
14 | using SharpSteer2.Helpers;
15 | using Vector3 = System.Numerics.Vector3;
16 |
17 | namespace Demo.PlugIns.Soccer
18 | {
19 | public class Player : SimpleVehicle
20 | {
21 | Trail _trail;
22 |
23 | public override float MaxForce { get { return 3000.7f; } }
24 | public override float MaxSpeed { get { return 10; } }
25 |
26 | // constructor
27 | public Player(List others, List allplayers, Ball ball, bool isTeamA, int id, IAnnotationService annotations = null)
28 | :base(annotations)
29 | {
30 | _allPlayers = allplayers;
31 | _ball = ball;
32 | _imTeamA = isTeamA;
33 | _myID = id;
34 |
35 | Reset();
36 | }
37 |
38 | // reset state
39 | public override void Reset()
40 | {
41 | base.Reset(); // reset the vehicle
42 | Speed = 0.0f; // speed along Forward direction.
43 |
44 | // Place me on my part of the field, looking at oponnents goal
45 | Position = new Vector3(_imTeamA ? RandomHelpers.Random() * 20 : -RandomHelpers.Random() * 20, 0, (RandomHelpers.Random() - 0.5f) * 20);
46 | if (_myID < 9)
47 | {
48 | Position = _imTeamA ? (Globals.PlayerPosition[_myID]) : (new Vector3(-Globals.PlayerPosition[_myID].X, Globals.PlayerPosition[_myID].Y, Globals.PlayerPosition[_myID].Z));
49 | }
50 | _home = Position;
51 |
52 | if (_trail == null) _trail = new Trail(10, 60);
53 | _trail.Clear(); // prevent long streaks due to teleportation
54 | }
55 |
56 | // per frame simulation update
57 | public void Update(float elapsedTime)
58 | {
59 | // if I hit the ball, kick it.
60 | float distToBall = Vector3.Distance(Position, _ball.Position);
61 | float sumOfRadii = Radius + _ball.Radius;
62 | if (distToBall < sumOfRadii)
63 | _ball.Kick((_ball.Position - Position) * 50);
64 |
65 | // otherwise consider avoiding collisions with others
66 | Vector3 collisionAvoidance = SteerToAvoidNeighbors(1, _allPlayers);
67 | if (collisionAvoidance != Vector3.Zero)
68 | ApplySteeringForce(collisionAvoidance, elapsedTime);
69 | else
70 | {
71 | float distHomeToBall = Vector3.Distance(_home, _ball.Position);
72 | if (distHomeToBall < 12)
73 | {
74 | // go for ball if I'm on the 'right' side of the ball
75 | if (_imTeamA ? Position.X > _ball.Position.X : Position.X < _ball.Position.X)
76 | {
77 | Vector3 seekTarget = SteerForSeek(_ball.Position);
78 | ApplySteeringForce(seekTarget, elapsedTime);
79 | }
80 | else
81 | {
82 | if (distHomeToBall < 12)
83 | {
84 | float z = _ball.Position.Z - Position.Z > 0 ? -1.0f : 1.0f;
85 | Vector3 behindBall = _ball.Position + (_imTeamA ? new Vector3(2, 0, z) : new Vector3(-2, 0, z));
86 | Vector3 behindBallForce = SteerForSeek(behindBall);
87 | annotation.Line(Position, behindBall, Color.Green.ToVector3().FromXna());
88 | Vector3 evadeTarget = SteerForFlee(_ball.Position);
89 | ApplySteeringForce(behindBallForce * 10 + evadeTarget, elapsedTime);
90 | }
91 | }
92 | }
93 | else // Go home
94 | {
95 | Vector3 seekTarget = SteerForSeek(_home);
96 | Vector3 seekHome = SteerForSeek(_home);
97 | ApplySteeringForce(seekTarget + seekHome, elapsedTime);
98 | }
99 |
100 | }
101 | }
102 |
103 | // draw this character/vehicle into the scene
104 | public void Draw()
105 | {
106 | Drawing.DrawBasic2dCircularVehicle(this, _imTeamA ? Color.Red : Color.Blue);
107 | _trail.Draw(annotation);
108 | }
109 |
110 | // per-instance reference to its group
111 | readonly List _allPlayers;
112 | readonly Ball _ball;
113 | readonly bool _imTeamA;
114 | readonly int _myID;
115 | Vector3 _home;
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/Demo/PlugIns/Soccer/SoccerPlugIn.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // Copyright (C) 2007 Michael Coles
5 | // All rights reserved.
6 | //
7 | // This software is licensed as described in the file license.txt, which
8 | // you should have received as part of this distribution. The terms
9 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
10 |
11 | using System;
12 | using System.Collections.Generic;
13 | using System.Text;
14 | using Microsoft.Xna.Framework;
15 | using SharpSteer2;
16 | using Vector3 = System.Numerics.Vector3;
17 |
18 | namespace Demo.PlugIns.Soccer
19 | {
20 | public class SoccerPlugIn : PlugIn
21 | {
22 | public SoccerPlugIn(IAnnotationService annotations = null)
23 | :base(annotations)
24 | {
25 | _teamA = new List();
26 | _teamB = new List();
27 | _allPlayers = new List();
28 | }
29 |
30 | public override String Name { get { return "Michael's Simple Soccer"; } }
31 |
32 | public override void Open()
33 | {
34 | // Make a field
35 | _bbox = new AABBox(new Vector3(-20, 0, -10), new Vector3(20, 0, 10));
36 | // Red goal
37 | _teamAGoal = new AABBox(new Vector3(-21, 0, -7), new Vector3(-19, 0, 7));
38 | // Blue Goal
39 | _teamBGoal = new AABBox(new Vector3(19, 0, -7), new Vector3(21, 0, 7));
40 | // Make a ball
41 | _ball = new Ball(_bbox);
42 | // Build team A
43 | const int PLAYER_COUNT_A = 8;
44 | for (int i = 0; i < PLAYER_COUNT_A; i++)
45 | {
46 | Player pMicTest = new Player(_teamA, _allPlayers, _ball, true, i, Annotations);
47 | Demo.SelectedVehicle = pMicTest;
48 | _teamA.Add(pMicTest);
49 | _allPlayers.Add(pMicTest);
50 | }
51 | // Build Team B
52 | const int PLAYER_COUNT_B = 8;
53 | for (int i = 0; i < PLAYER_COUNT_B; i++)
54 | {
55 | Player pMicTest = new Player(_teamB, _allPlayers, _ball, false, i, Annotations);
56 | Demo.SelectedVehicle = pMicTest;
57 | _teamB.Add(pMicTest);
58 | _allPlayers.Add(pMicTest);
59 | }
60 | // initialize camera
61 | Demo.Init2dCamera(_ball);
62 | Demo.Camera.Position = new Vector3(10, Demo.CAMERA2_D_ELEVATION, 10);
63 | Demo.Camera.FixedPosition = new Vector3(40);
64 | Demo.Camera.Mode = Camera.CameraMode.Fixed;
65 | _redScore = 0;
66 | _blueScore = 0;
67 | }
68 |
69 | public override void Update(float currentTime, float elapsedTime)
70 | {
71 | // update simulation of test vehicle
72 | foreach (Player player in _teamA)
73 | player.Update(elapsedTime);
74 | foreach (Player player in _teamB)
75 | player.Update(elapsedTime);
76 | _ball.Update(currentTime, elapsedTime);
77 |
78 | if (_teamAGoal.IsInsideX(_ball.Position) && _teamAGoal.IsInsideZ(_ball.Position))
79 | {
80 | _ball.Reset(); // Ball in blue teams goal, red scores
81 | _redScore++;
82 | }
83 | if (_teamBGoal.IsInsideX(_ball.Position) && _teamBGoal.IsInsideZ(_ball.Position))
84 | {
85 | _ball.Reset(); // Ball in red teams goal, blue scores
86 | _blueScore++;
87 | }
88 | }
89 |
90 | public override void Redraw(float currentTime, float elapsedTime)
91 | {
92 | // draw "ground plane"
93 | Demo.GridUtility(Vector3.Zero);
94 |
95 | // draw test vehicle
96 | foreach (Player player in _teamA)
97 | player.Draw();
98 | foreach (Player player in _teamB)
99 | player.Draw();
100 | _ball.Draw();
101 | _bbox.Draw();
102 | _teamAGoal.Draw();
103 | _teamBGoal.Draw();
104 |
105 | StringBuilder annote = new StringBuilder();
106 | annote.AppendFormat("Red: {0}", _redScore);
107 | Drawing.Draw2dTextAt3dLocation(annote.ToString(), new Vector3(23, 0, 0), new Color((byte)(255.0f * 1), (byte)(255.0f * 0.7f), (byte)(255.0f * 0.7f)));
108 |
109 | annote = new StringBuilder();
110 | annote.AppendFormat("Blue: {0}", _blueScore);
111 | Drawing.Draw2dTextAt3dLocation(annote.ToString(), new Vector3(-23, 0, 0), new Color((byte)(255.0f * 0.7f), (byte)(255.0f * 0.7f), (byte)(255.0f * 1)));
112 |
113 | // textual annotation (following the test vehicle's screen position)
114 | #if IGNORED
115 | for (int i = 0; i < TeamA.Count; i++)
116 | {
117 | String anno = String.Format(" speed: {0:0.00} ID: {1} ", TeamA[i].speed(), i);
118 | Drawing.Draw2dTextAt3dLocation(anno, TeamA[i].position(), Color.Red);
119 | }
120 | Drawing.Draw2dTextAt3dLocation("start", Vector3.zero, Color.Green);
121 | #endif
122 | // update camera, tracking test vehicle
123 | Demo.UpdateCamera(elapsedTime, Demo.SelectedVehicle);
124 | }
125 |
126 | public override void Close()
127 | {
128 | _teamA.Clear();
129 | _teamB.Clear();
130 | _allPlayers.Clear();
131 | }
132 |
133 | public override void Reset()
134 | {
135 | // reset vehicle
136 | foreach (Player player in _teamA)
137 | player.Reset();
138 | foreach (Player player in _teamB)
139 | player.Reset();
140 | _ball.Reset();
141 | }
142 |
143 | //const AVGroup& allVehicles () {return (const AVGroup&) TeamA;}
144 | public override IEnumerable Vehicles
145 | {
146 | get { return _teamA.ConvertAll(p => (IVehicle) p); }
147 | }
148 |
149 | readonly List _teamA;
150 | readonly List _teamB;
151 | readonly List _allPlayers;
152 |
153 | Ball _ball;
154 | AABBox _bbox;
155 | AABBox _teamAGoal;
156 | AABBox _teamBGoal;
157 | int _redScore;
158 | int _blueScore;
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/Demo/Program.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2002-2003, Sony Computer Entertainment America
2 | // Copyright (c) 2002-2003, Craig Reynolds
3 | // Copyright (C) 2007 Bjoern Graf
4 | // All rights reserved.
5 | //
6 | // This software is licensed as described in the file license.txt, which
7 | // you should have received as part of this distribution. The terms
8 | // are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.
9 |
10 | // SharpSteer - Steering Behaviors for Autonomous Characters
11 | namespace Demo
12 | {
13 | static class Program
14 | {
15 | ///
16 | /// The main entry point for the application.
17 | ///
18 | static void Main(string[] args)
19 | {
20 | using (Demo demo = new Demo())
21 | {
22 | demo.Run();
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Demo/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("SharpSteer Demo")]
8 | [assembly: AssemblyProduct("SharpSteer Demo")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyCompany("")]
11 |
12 | [assembly: AssemblyCopyright("Copyright © 2007")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("6eda8076-3da1-407a-9cf9-5aea2fa44752")]
23 |
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | [assembly: AssemblyVersion("1.0.0.0")]
33 |
--------------------------------------------------------------------------------
/Demo/SimpleFlowField.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Numerics;
3 | using SharpSteer2;
4 | using SharpSteer2.Helpers;
5 |
6 | namespace Demo
7 | {
8 | public class SimpleFlowField
9 | : IFlowField
10 | {
11 | private readonly Vector3 _center;
12 |
13 | private readonly Vector3[,,] _field;
14 |
15 | public SimpleFlowField(int x, int y, int z, Vector3 center)
16 | {
17 | _center = center;
18 | _field = new Vector3[x, y, z];
19 | }
20 |
21 | public Vector3 Sample(Vector3 location)
22 | {
23 | var sampleLocation = location + _center;
24 | var sample = _field[
25 | (int)Utilities.Clamp(sampleLocation.X, 0, _field.GetLength(0) - 1),
26 | (int)Utilities.Clamp(sampleLocation.Y, 0, _field.GetLength(1) - 1),
27 | (int)Utilities.Clamp(sampleLocation.Z, 0, _field.GetLength(2) - 1)
28 | ];
29 |
30 | return sample;
31 | }
32 |
33 | public void Func(Func func, float weight)
34 | {
35 | for (int i = 0; i < _field.GetLength(0); i++)
36 | {
37 | for (int j = 0; j < _field.GetLength(1); j++)
38 | {
39 | for (int k = 0; k < _field.GetLength(2); k++)
40 | {
41 | var pos = new Vector3(i, j, k) - _center;
42 | _field[i, j, k] = Vector3.Lerp(_field[i, j, k], func(pos), weight);
43 | }
44 | }
45 | }
46 | }
47 |
48 | public void Randomize(float weight)
49 | {
50 | Func(_ => Vector3Helpers.RandomUnitVector(), weight);
51 | }
52 |
53 | public void ClampXZ()
54 | {
55 | for (int i = 0; i < _field.GetLength(0); i++)
56 | {
57 | for (int j = 0; j < _field.GetLength(1); j++)
58 | {
59 | for (int k = 0; k < _field.GetLength(2); k++)
60 | {
61 | _field[i, j, k] = new Vector3(_field[i, j, k].X, 0, _field[i, j, k].Z);
62 | }
63 | }
64 | }
65 | }
66 |
67 | public void Normalize()
68 | {
69 | for (int i = 0; i < _field.GetLength(0); i++)
70 | {
71 | for (int j = 0; j < _field.GetLength(1); j++)
72 | {
73 | for (int k = 0; k < _field.GetLength(2); k++)
74 | {
75 | _field[i, j, k] = Vector3.Normalize(_field[i, j, k]);
76 | }
77 | }
78 | }
79 | }
80 |
81 | public void Clean()
82 | {
83 | for (int i = 0; i < _field.GetLength(0); i++)
84 | {
85 | for (int j = 0; j < _field.GetLength(1); j++)
86 | {
87 | for (int k = 0; k < _field.GetLength(2); k++)
88 | {
89 | var v = _field[i, j, k];
90 | if (float.IsNaN(v.X) || float.IsNaN(v.Y) || float.IsNaN(v.Z))
91 | _field[i, j, k] = Vector3.Zero;
92 | }
93 | }
94 | }
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/Demo/Trail.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.Xna.Framework;
3 | using SharpSteer2;
4 | using Vector3 = System.Numerics.Vector3;
5 |
6 | namespace Demo
7 | {
8 | ///
9 | /// Provides support to visualize the recent path of a vehicle.
10 | ///
11 | public class Trail
12 | {
13 | int _currentIndex; // Array index of most recently recorded point
14 | readonly float _sampleInterval; // Desired interval between taking samples
15 | float _lastSampleTime; // Global time when lat sample was taken
16 | int _dottedPhase; // Dotted line: draw segment or not
17 | Vector3 _currentPosition; // Last reported position of vehicle
18 | readonly Vector3[] _vertices; // Array (ring) of recent points along trail
19 | readonly byte[] _flags; // Array (ring) of flag bits for trail points
20 | Color _trailColor; // Color of the trail
21 | Color _tickColor; // Color of the ticks
22 |
23 | ///
24 | /// Initializes a new instance of Trail.
25 | ///
26 | public Trail()
27 | : this(5, 100)
28 | {
29 | }
30 |
31 | ///
32 | /// Initializes a new instance of Trail.
33 | ///
34 | /// The amount of time the trail represents.
35 | /// The number of smaples along the trails length.
36 | public Trail(float duration, int vertexCount)
37 | {
38 | // Set internal trail state
39 | _currentIndex = 0;
40 | _lastSampleTime = 0;
41 | _sampleInterval = duration / vertexCount;
42 | _dottedPhase = 1;
43 |
44 | // Initialize ring buffers
45 | _vertices = new Vector3[vertexCount];
46 | _flags = new byte[vertexCount];
47 |
48 | _trailColor = Color.LightGray;
49 | _tickColor = Color.White;
50 | }
51 |
52 | ///
53 | /// Gets or sets the color of the trail.
54 | ///
55 | public Color TrailColor
56 | {
57 | get { return _trailColor; }
58 | set { _trailColor = value; }
59 | }
60 |
61 | ///
62 | /// Gets or sets the color of the ticks.
63 | ///
64 | public Color TickColor
65 | {
66 | get { return _tickColor; }
67 | set { _tickColor = value; }
68 | }
69 |
70 | ///
71 | /// Records a position for the current time, called once per update.
72 | ///
73 | ///
74 | ///
75 | public void Record(float currentTime, Vector3 position)
76 | {
77 | float timeSinceLastTrailSample = currentTime - _lastSampleTime;
78 | if (timeSinceLastTrailSample > _sampleInterval)
79 | {
80 | _currentIndex = (_currentIndex + 1) % _vertices.Length;
81 | _vertices[_currentIndex] = position;
82 | _dottedPhase = (_dottedPhase + 1) % 2;
83 | bool tick = (Math.Floor(currentTime) > Math.Floor(_lastSampleTime));
84 | _flags[_currentIndex] = (byte)(_dottedPhase | (tick ? 2 : 0));
85 | _lastSampleTime = currentTime;
86 | }
87 | _currentPosition = position;
88 | }
89 |
90 | ///
91 | /// Draws the trail as a dotted line, fading away with age.
92 | ///
93 | public void Draw(IAnnotationService annotation)
94 | {
95 | int index = _currentIndex;
96 | for (int j = 0; j < _vertices.Length; j++)
97 | {
98 | // index of the next vertex (mod around ring buffer)
99 | int next = (index + 1) % _vertices.Length;
100 |
101 | // "tick mark": every second, draw a segment in a different color
102 | bool tick = ((_flags[index] & 2) != 0 || (_flags[next] & 2) != 0);
103 | Color color = tick ? _tickColor : _trailColor;
104 |
105 | // draw every other segment
106 | if ((_flags[index] & 1) != 0)
107 | {
108 | if (j == 0)
109 | {
110 | // draw segment from current position to first trail point
111 | annotation.Line(_currentPosition, _vertices[index], color.ToVector3().FromXna());
112 | }
113 | else
114 | {
115 | // draw trail segments with opacity decreasing with age
116 | const float MIN_O = 0.05f; // minimum opacity
117 | float fraction = (float)j / _vertices.Length;
118 | float opacity = (fraction * (1 - MIN_O)) + MIN_O;
119 | annotation.Line(_vertices[index], _vertices[next], color.ToVector3().FromXna(), opacity);
120 | }
121 | }
122 | index = next;
123 | }
124 | }
125 |
126 | ///
127 | /// Clear trail history. Used to prevent long streaks due to teleportation.
128 | ///
129 | public void Clear()
130 | {
131 | _currentIndex = 0;
132 | _lastSampleTime = 0;
133 | _dottedPhase = 1;
134 |
135 | for (int i = 0; i < _vertices.Length; i++)
136 | {
137 | _vertices[i] = Vector3.Zero;
138 | _flags[i] = 0;
139 | }
140 | }
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/License.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/martindevans/SharpSteer2/d8138fe95e81b38b62b864e457b23b94d9750199/License.txt
--------------------------------------------------------------------------------
/Local.testsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 | These are default test settings for a local test run.
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/SharpSteer2.Tests/LocalSpaceBasisHelpersTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 | using System.Numerics;
4 | using SharpSteer2.Helpers;
5 |
6 | namespace SharpSteer2.Tests
7 | {
8 | [TestClass]
9 | public class LocalSpaceBasisHelpersTest
10 | {
11 | // ReSharper disable once InconsistentNaming
12 | public const float PiOver2 = (float)Math.PI / 2f;
13 |
14 | private static ILocalSpaceBasis Basis(Matrix4x4 m)
15 | {
16 | return new LocalSpace(m);
17 | }
18 |
19 | [TestMethod]
20 | public void GlobalizeDirectionTest()
21 | {
22 | Matrix4x4 m = Matrix4x4.CreateRotationX(-PiOver2);
23 | ILocalSpaceBasis basis = Basis(m);
24 |
25 | var v = Vector3.Normalize(new Vector3(1, 2, 3));
26 | Assert.AreEqual(Vector3.TransformNormal(v, m), basis.GlobalizeDirection(v));
27 | }
28 |
29 | [TestMethod]
30 | public void GlobalizePositionTest()
31 | {
32 | Matrix4x4 m = Matrix4x4.CreateRotationX(-PiOver2) * Matrix4x4.CreateTranslation(10, 20, 30);
33 | ILocalSpaceBasis basis = Basis(m);
34 |
35 | var v = Vector3.Normalize(new Vector3(1, 2, 3));
36 | Assert.AreEqual(Vector3.Transform(v, m), basis.GlobalizePosition(v));
37 | }
38 |
39 | [TestMethod]
40 | public void LocalizeDirectionTest()
41 | {
42 | Matrix4x4 m = Matrix4x4.CreateRotationX(-PiOver2);
43 | ILocalSpaceBasis basis = Basis(m);
44 |
45 | var v = Vector3.Normalize(new Vector3(1, 2, 3));
46 | Matrix4x4 inv;
47 | Matrix4x4.Invert(m, out inv);
48 | Assert.AreEqual(Vector3.TransformNormal(v, inv), basis.LocalizeDirection(v));
49 | }
50 |
51 | [TestMethod]
52 | public void LocalizePositionTest()
53 | {
54 | Matrix4x4 m = Matrix4x4.CreateRotationX(-PiOver2) * Matrix4x4.CreateTranslation(10, 20, 30);
55 | ILocalSpaceBasis basis = Basis(m);
56 |
57 | var v = Vector3.Normalize(new Vector3(1, 2, 3));
58 | Matrix4x4 inv;
59 | Matrix4x4.Invert(m, out inv);
60 | Assert.AreEqual(Vector3.Transform(v, inv), basis.LocalizePosition(v));
61 | }
62 |
63 | [TestMethod]
64 | public void LocalRotateForwardToSideTest()
65 | {
66 | var f = new Vector3(0, 0, 1);
67 | var s = new Vector3(-1, 0, 0);
68 |
69 | Assert.AreEqual(s, LocalSpaceBasisHelpers.LocalRotateForwardToSide(null, f));
70 | }
71 |
72 | [TestMethod]
73 | public void RegenerateOrthonormalBasisTest()
74 | {
75 | var f = Vector3.UnitZ * 2;
76 | var u = Vector3.UnitY;
77 |
78 | Vector3 s;
79 | LocalSpaceBasisHelpers.RegenerateOrthonormalBasis(f, u, out f, out s, out u);
80 |
81 | Assert.AreEqual(Vector3.UnitZ, f);
82 | Assert.AreEqual(u, Vector3.UnitY);
83 | Assert.AreEqual(Vector3.Cross(f, u), s);
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/SharpSteer2.Tests/LocalityQueryProximityDatabaseTest.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using Microsoft.VisualStudio.TestTools.UnitTesting;
4 | using System.Numerics;
5 | using SharpSteer2.Database;
6 |
7 | namespace SharpSteer2.Tests
8 | {
9 | [TestClass]
10 | public class LocalityQueryProximityDatabaseTest
11 | {
12 | [TestMethod]
13 | public void Construct()
14 | {
15 | var db = new LocalityQueryProximityDatabase