├── README.md ├── CollisionDetectionSelector ├── App.config ├── packages.config ├── Samples │ ├── ConsoleSample.cs │ ├── PointSample.cs │ ├── OBJSample.cs │ ├── WindowSample.cs │ ├── OBJDebugTriangles.cs │ ├── SampleSphere.cs │ ├── OBJClassSample.cs │ ├── TriangleSphereIntersection.cs │ ├── PlanePlaneIntersection.cs │ ├── SphereAABBIntersection.cs │ ├── AABBPlaneIntersection.cs │ ├── TrianglePlaneIntersection.cs │ ├── TriangleTriangleIntersection.cs │ ├── SpherePlaneIntersection.cs │ ├── AABBAABBIntersection.cs │ ├── SphereSphereIntersection.cs │ ├── RaycastAABB.cs │ ├── LinecastSphere.cs │ ├── TriangleAABBIntersection.cs │ ├── LinecastAABB.cs │ ├── LinecastPlane.cs │ ├── OBJDebugTrianglesAABB.cs │ ├── RaycastPlane.cs │ ├── RaycastTriangle.cs │ ├── ClosestPointTriangle.cs │ ├── OBJRaycast.cs │ ├── OBJSphereIntersection.cs │ ├── OBJTrianglesSphere.cs │ ├── OBJPlaneIntersection.cs │ ├── RaycastSphere.cs │ ├── OBJTriangleIntersection.cs │ ├── OBJAABBIntersection.cs │ ├── PointInTriangleSample.cs │ ├── ClosesPointOnPlane.cs │ ├── PlaneSample.cs │ ├── PointOnLineSample.cs │ ├── ClosestPointOnLineSample.cs │ ├── LineSample.cs │ ├── PointOnRay.cs │ ├── RaySample.cs │ ├── ClosestPointOnRay.cs │ ├── PickingExample.cs │ ├── SceneSample.cs │ ├── OctreeSample.cs │ ├── AABBPointSample.cs │ ├── ClosestPointSample.cs │ ├── PointOnPlaneSample.cs │ └── AABBSample.cs ├── Primitive │ ├── Triangle.cs │ ├── Line.cs │ ├── Ray.cs │ ├── Point.cs │ ├── LinetestTriangle.cs │ ├── Plane.cs │ ├── AABB.cs │ ├── Sphere.cs │ ├── Camera.cs │ └── OBJ.cs ├── Scene.cs ├── Properties │ └── AssemblyInfo.cs ├── Math │ ├── MatrixStack.cs │ ├── Vector4.cs │ ├── Vector3.cs │ └── Vector2.cs ├── OpenTK.dll.config ├── Program.cs ├── BVH.cs └── Application.cs ├── CollisionDetection.sln └── .gitignore /README.md: -------------------------------------------------------------------------------- 1 | # 3DCollisions 2 | Collisions in 3D and maths exercises pertaining to it 3 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/ConsoleSample.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CollisionDetection.Samples { 4 | class ConsoleSample : Application { 5 | public override void Main(string[] args) { 6 | Console.WriteLine("Testing,testing"); 7 | Console.WriteLine("No window should pop up"); 8 | Console.WriteLine("Press any key to quit"); 9 | Console.ReadKey(); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /CollisionDetection.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.24720.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CollisionDetectionSelector", "CollisionDetectionSelector\CollisionDetectionSelector.csproj", "{873DA658-017D-47A7-9A5A-A680405D70A4}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {873DA658-017D-47A7-9A5A-A680405D70A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {873DA658-017D-47A7-9A5A-A680405D70A4}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {873DA658-017D-47A7-9A5A-A680405D70A4}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {873DA658-017D-47A7-9A5A-A680405D70A4}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/Primitive/Triangle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using OpenTK.Graphics.OpenGL; 3 | using Math_Implementation; 4 | 5 | namespace CollisionDetectionSelector.Primitive { 6 | class Triangle { 7 | public Point p0 = new Point(); 8 | public Point p1 = new Point(); 9 | public Point p2 = new Point(); 10 | public Triangle() { 11 | 12 | } 13 | public Triangle(Point _p0,Point _p1,Point _p2) { 14 | p0 = new Point(_p0.ToVector()); 15 | p1 = new Point(_p1.ToVector()); 16 | p2 = new Point(_p2.ToVector()); 17 | } 18 | public Triangle(Vector3 _p0,Vector3 _p1,Vector3 _p2) { 19 | p0 = new Point(_p0); 20 | p1 = new Point(_p1); 21 | p2 = new Point(_p2); 22 | } 23 | public void Render() { 24 | GL.Begin(PrimitiveType.Triangles); 25 | GL.Vertex3(p0.X,p0.Y,p0.Z); 26 | GL.Vertex3(p1.X, p1.Y, p1.Z); 27 | GL.Vertex3(p2.X, p2.Y, p2.Z); 28 | GL.End(); 29 | } 30 | public override string ToString() { 31 | return "p0: " + p0.ToString() + ", p1: " + p1.ToString() + ", p2: " + p2.ToString(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/Scene.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using System.Collections.Generic; 3 | using Math_Implementation; 4 | using CollisionDetectionSelector.Primitive; 5 | 6 | namespace CollisionDetectionSelector { 7 | class Scene { 8 | public OBJ RootObject = new OBJ(null); //always null 9 | public OctreeNode Octree = null; 10 | 11 | public void Initialize(float octreeSize) { 12 | Octree = new OctreeNode(new Point(0, 0, 0), octreeSize, null); 13 | Octree.Split(3); 14 | } 15 | 16 | public int Render(bool debug) { 17 | int result = RootObject.Render(); 18 | 19 | if (debug) { 20 | GL.Disable(EnableCap.Lighting); 21 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 22 | Octree.DebugRender(); 23 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); 24 | Octree.DebugRenderOnlyVisitedNodes(); 25 | GL.Enable(EnableCap.Lighting); 26 | 27 | } 28 | return result; 29 | } 30 | 31 | public OBJ Raycast(Ray ray, out float t) { 32 | return Octree.Raycast(ray, out t); 33 | } 34 | public OBJ Raycast(Ray ray) { 35 | float t = 0.0f; 36 | return Octree.Raycast(ray, out t); 37 | } 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/PointSample.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class PointSample : Application { 7 | Point[] points = null; 8 | 9 | public override void Initialize(int width, int height) { 10 | points = new Point[100]; 11 | for (int i = 0; i < 100; ++i) { 12 | points[i] = new Point(i - 50, i - 50, i - 50); 13 | } 14 | GL.PointSize(2f); 15 | } 16 | 17 | public override void Render() { 18 | Matrix4 lookAt = Matrix4.LookAt(new Vector3(0.0f, 0.0f, 30.0f), new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f)); 19 | GL.LoadMatrix(lookAt.OpenGL); 20 | 21 | for (int i = 0; i < points.Length; ++i) { 22 | points[i].Render(); 23 | } 24 | } 25 | 26 | public override void Resize(int width, int height) { 27 | GL.Viewport(0, 0, width, height); 28 | GL.MatrixMode(MatrixMode.Projection); 29 | float aspect = (float)width / (float)height; 30 | Matrix4 perspective = Matrix4.Perspective(60, aspect, 0.01f, 1000.0f); 31 | GL.LoadMatrix(Matrix4.Transpose(perspective).Matrix); 32 | GL.MatrixMode(MatrixMode.Modelview); 33 | GL.LoadIdentity(); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/OBJSample.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | using CollisionDetectionSelector; 5 | 6 | namespace CollisionDetectionSelector.Samples { 7 | class OBJSample : Application { 8 | OBJLoader obj = null; 9 | 10 | public override void Initialize(int width, int height) { 11 | GL.Enable(EnableCap.DepthTest); 12 | GL.Enable(EnableCap.CullFace); 13 | GL.Enable(EnableCap.Lighting); 14 | GL.Enable(EnableCap.Light0); 15 | 16 | GL.Light(LightName.Light0, LightParameter.Position, new float[] { 0.0f, 0.5f, 0.5f, 0.0f }); 17 | GL.Light(LightName.Light0, LightParameter.Ambient, new float[] { 0f, 1f, 0f, 1f }); 18 | GL.Light(LightName.Light0, LightParameter.Diffuse, new float[] { 0f, 1f, 0f, 1f }); 19 | GL.Light(LightName.Light0, LightParameter.Specular, new float[] { 1f, 1f, 1f, 1f }); 20 | 21 | obj = new OBJLoader("Assets/suzanne.obj"); 22 | } 23 | 24 | public override void Render() { 25 | base.Render(); 26 | DrawOrigin(); 27 | 28 | GL.PushMatrix(); 29 | GL.Scale(3.0f, 3.0f, 3.0f); 30 | //obj.Render(); 31 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 32 | obj.RenderBVH(); 33 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); 34 | GL.PopMatrix(); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/WindowSample.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using OpenTK.Graphics.OpenGL; 7 | using Math_Implementation; 8 | 9 | namespace CollisionDetectionSelector.Samples { 10 | class WindowedSample : Application { 11 | public override void Render() { 12 | Matrix4 lookAt = Matrix4.LookAt(new Vector3(0.0f, 0.0f, 30.0f), new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f)); 13 | GL.LoadMatrix(lookAt.OpenGL); 14 | 15 | GL.ShadeModel(ShadingModel.Smooth); 16 | 17 | GL.Begin(PrimitiveType.Triangles); 18 | GL.Color3(1.0f, 0.0f, 0.0f); 19 | GL.Vertex3(-10.0f, -10.0f, -5.0f);//red 20 | GL.Color3(0.0f, 1.0f, 0.0f); 21 | GL.Vertex3(20.0f, -10.0f, -5.0f);//green 22 | GL.Color3(0.0f, 0.0f, 1.0f); 23 | GL.Vertex3(-10.0f, 20.0f, -5.0f);//blue 24 | GL.End(); 25 | } 26 | 27 | public override void Resize(int width, int height) { 28 | GL.Viewport(0, 0, width, height); 29 | GL.MatrixMode(MatrixMode.Projection); 30 | float aspect = (float)width / (float)height; 31 | Matrix4 perspective = Matrix4.Perspective(60, aspect, 0.01f, 1000.0f); 32 | GL.LoadMatrix(Matrix4.Transpose(perspective).Matrix); 33 | GL.MatrixMode(MatrixMode.Modelview); 34 | GL.LoadIdentity(); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/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("CollisionDetectionSelector")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("CollisionDetectionSelector")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("873da658-017d-47a7-9a5a-a680405d70a4")] 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 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/OBJDebugTriangles.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | using CollisionDetectionSelector; 5 | 6 | namespace CollisionDetectionSelector.Samples { 7 | class OBJDebugTriangles : Application { 8 | OBJLoader obj = null; 9 | 10 | public override void Initialize(int width, int height) { 11 | GL.Enable(EnableCap.DepthTest); 12 | GL.Enable(EnableCap.CullFace); 13 | GL.Enable(EnableCap.Lighting); 14 | GL.Enable(EnableCap.Light0); 15 | 16 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 17 | 18 | GL.Light(LightName.Light0, LightParameter.Position, new float[] { 0.0f, 0.5f, 0.5f, 0.0f }); 19 | GL.Light(LightName.Light0, LightParameter.Ambient, new float[] { 0f, 1f, 0f, 1f }); 20 | GL.Light(LightName.Light0, LightParameter.Diffuse, new float[] { 0f, 1f, 0f, 1f }); 21 | GL.Light(LightName.Light0, LightParameter.Specular, new float[] { 1f, 1f, 1f, 1f }); 22 | 23 | obj = new OBJLoader("Assets/suzanne.obj"); 24 | 25 | if (obj.NumCollisionTriangles != 968) { 26 | LogError("Suzanne triangle count expected at 968, got: " + obj.NumCollisionTriangles); 27 | } 28 | } 29 | 30 | public override void Render() { 31 | base.Render(); 32 | DrawOrigin(); 33 | 34 | GL.PushMatrix(); 35 | GL.Scale(3.0f, 3.0f, 3.0f); 36 | obj.DebugRender(); 37 | GL.PopMatrix(); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Primitive/Line.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using OpenTK.Graphics.OpenGL; 3 | using Math_Implementation; 4 | 5 | namespace CollisionDetectionSelector.Primitive { 6 | class Line { 7 | public Point Start; 8 | public Point End; 9 | public float Length { 10 | get { 11 | Vector3 line = End.ToVector() - Start.ToVector(); 12 | return line.Length(); 13 | } 14 | } 15 | public float LengthSq { 16 | get { 17 | Vector3 line = End.ToVector()-Start.ToVector(); 18 | return line.LengthSquared(); 19 | } 20 | } 21 | public Line(Line copy) { 22 | Start = new Point(copy.Start.X,copy.Start.Y,copy.Start.Z); 23 | End = new Point(copy.End.X,copy.End.Y,copy.End.Z); 24 | } 25 | public Line(Point p1, Point p2) { 26 | Start = new Point(p1); 27 | End = new Point(p2); 28 | } 29 | public Vector3 ToVector() { 30 | return new Vector3(End.X - Start.X, End.Y - Start.Y, End.Z - Start.Z); 31 | } 32 | public void Render() { 33 | GL.Begin(PrimitiveType.Lines); 34 | GL.Vertex3(Start.X, Start.Y, Start.Z); 35 | GL.Vertex3(End.X, End.Y, End.Z); 36 | GL.End(); 37 | } 38 | public override string ToString() { 39 | string result = "Start: (" + Start.X + ", " + Start.Y + ", " + Start.Z + "), "; 40 | result += "End: ( " + End.X + ", " + End.Y + ", " + End.Z + ")"; 41 | return result; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/Math/MatrixStack.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Math_Implementation { 8 | class MatrixStack { 9 | protected List stack = null; 10 | public int Count { 11 | get { 12 | if (stack != null) { 13 | return 0; 14 | } 15 | return stack.Count; 16 | } 17 | } 18 | public Matrix4 this[int i] { 19 | get { 20 | return stack[i]; 21 | } 22 | 23 | } 24 | public MatrixStack() { 25 | stack = new List(); 26 | stack.Add(new Matrix4()); 27 | } 28 | public void Push() { 29 | //new matrix 30 | Matrix4 top = new Matrix4(); 31 | //copy values of top matrix 32 | for (int i = 0; i < stack[stack.Count - 1].Matrix.Length; i++) { 33 | top.Matrix[i] = stack[stack.Count-1].Matrix[i]; 34 | } 35 | //add new copy to top 36 | stack.Add(top); 37 | } 38 | public void Load(Matrix4 matrix) { 39 | for (int i = 0; i 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/OBJClassSample.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | using CollisionDetectionSelector; 5 | 6 | namespace CollisionDetectionSelector.Samples { 7 | class OBJClassSample : Application { 8 | OBJLoader loader = null; 9 | OBJ[] objs = new OBJ[] { null, null, null }; 10 | 11 | public override void Initialize(int width, int height) { 12 | GL.Enable(EnableCap.DepthTest); 13 | GL.Enable(EnableCap.CullFace); 14 | GL.Enable(EnableCap.Lighting); 15 | GL.Enable(EnableCap.Light0); 16 | 17 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 18 | 19 | GL.Light(LightName.Light0, LightParameter.Position, new float[] { 0.0f, 0.5f, 0.5f, 0.0f }); 20 | GL.Light(LightName.Light0, LightParameter.Ambient, new float[] { 0f, 1f, 0f, 1f }); 21 | GL.Light(LightName.Light0, LightParameter.Diffuse, new float[] { 0f, 1f, 0f, 1f }); 22 | GL.Light(LightName.Light0, LightParameter.Specular, new float[] { 1f, 1f, 1f, 1f }); 23 | 24 | loader = new OBJLoader("Assets/suzanne.obj"); 25 | objs[0] = new OBJ(loader); 26 | objs[1] = new OBJ(loader); 27 | objs[2] = new OBJ(loader); 28 | 29 | objs[0].Scale = new Vector3(3.0f, 3.0f, 3.0f); 30 | 31 | objs[1].Position = new Vector3(6.0f, 6.0f, 6.0f); 32 | objs[1].Scale = new Vector3(1.5f, 1.5f, 1.5f); 33 | 34 | objs[2].Position = new Vector3(-6.0f, -6.0f, -6.0f); 35 | objs[1].Scale = new Vector3(1.5f, 1.5f, 1.5f); 36 | objs[2].Rotation = new Vector3(90.0f, 0.0f, 0.0f); 37 | } 38 | 39 | public override void Render() { 40 | base.Render(); 41 | DrawOrigin(); 42 | 43 | 44 | foreach (OBJ obj in objs) { 45 | obj.DebugRender(); 46 | 47 | } 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/TriangleSphereIntersection.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class TriangleSphereIntersection : Application { 7 | Sphere[] spheres = new Sphere[] { 8 | new Sphere(new Point(2, 4, -1), 0.5f), 9 | new Sphere(new Point(-1.0f, 5.0f, 0.0f), 0.5f), 10 | new Sphere(new Point(2f, 2f, 2f), 1f), 11 | new Sphere(new Point(-2f, -2f, -2f), 1f) 12 | }; 13 | 14 | Triangle triangle = new Triangle(new Point(-1.0f, 5.0f, 0.0f), new Point(2.0f, 2.0f, -3.0f), new Point(5.0f, 5.0f, 0.0f)); 15 | 16 | public override void Initialize(int width, int height) { 17 | GL.Enable(EnableCap.DepthTest); 18 | GL.PointSize(4f); 19 | GL.Disable(EnableCap.CullFace); 20 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 21 | 22 | bool[] expected = new bool[] { true, true, false, false }; 23 | for (int i = 0; i < spheres.Length; ++i) { 24 | bool result = Collisions.SphereIntersect(triangle, spheres[i]); 25 | if (result != expected[i]) { 26 | LogError("Expected sphere " + i + " to " + 27 | (expected[i] ? " intersect" : " NOT intersect") + 28 | " the triangle"); 29 | } 30 | } 31 | } 32 | 33 | public override void Render() { 34 | base.Render(); 35 | DrawOrigin(); 36 | 37 | GL.Color3(0.0f, 0.0f, 1.0f); 38 | triangle.Render(); 39 | 40 | foreach (Sphere sphere in spheres) { 41 | if (Collisions.SphereIntersect(triangle, sphere)) { 42 | GL.Color3(0f, 1f, 0f); 43 | } 44 | else { 45 | GL.Color3(1f, 0f, 0f); 46 | } 47 | sphere.Render(); 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/PlanePlaneIntersection.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class PlanePlaneIntersection : Application { 7 | Plane[] planes = new Plane[] { 8 | null, null, null, null, null // Size = 5 9 | }; 10 | 11 | public override void Initialize(int width, int height) { 12 | GL.Enable(EnableCap.DepthTest); 13 | //GL.Enable(EnableCap.CullFace); 14 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 15 | GL.PointSize(5f); 16 | 17 | planes[0] = new Plane(); 18 | planes[1] = new Plane(new Vector3(2f, 0f, 1f), 0f); 19 | planes[2] = new Plane(new Vector3(0f, 1f, 0f), -2f); 20 | planes[3] = new Plane(new Vector3(-1f, 1f, 2f), 3f); 21 | planes[4] = new Plane(new Vector3(1f, 0f, 0.5f), 3f); 22 | 23 | bool[] results = new bool[] { 24 | false, true, true, true, true, true, false, true, true, false, true, 25 | true, false, true, true, true, true, true, false, true, true, false, 26 | true, true, false, 27 | }; 28 | int t = 0; 29 | 30 | for (int i = 0; i < planes.Length; ++i) { 31 | for (int j = 0; j < planes.Length; ++j) { 32 | if (Intersects.PlanePlaneIntersect(planes[i], planes[j]) != results[t++]) { 33 | LogError("[" + (t - 1) + "] Expected plane " + i + " to " + 34 | (results[t - 1] ? "intersect" : "not intersect") + 35 | " plane " + j); 36 | } 37 | } 38 | } 39 | } 40 | 41 | public override void Render() { 42 | base.Render(); 43 | DrawOrigin(); 44 | 45 | for (int i = 0; i < planes.Length; ++i) { 46 | planes[i].Render(); 47 | } 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/SphereAABBIntersection.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class SphereAABBIntersection : Application { 7 | Sphere test = new Sphere(new Point(1f, 0f, 1f), 2f); 8 | 9 | AABB[] aabbs = new AABB[] { 10 | null, null, null, null // Size = 4 11 | }; 12 | 13 | public override void Initialize(int width, int height) { 14 | GL.Enable(EnableCap.DepthTest); 15 | GL.Enable(EnableCap.CullFace); 16 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 17 | GL.PointSize(5f); 18 | 19 | aabbs[0] = new AABB(new Point(-2f, -2f, -2f), new Point(-1f, -1f, -1f)); 20 | aabbs[1] = new AABB(new Point(2f, 1f, 2f), new Point(4f, 3f, 4f)); 21 | aabbs[2] = new AABB(new Point(1f, 0f, 1f), new Point(0f, -1f, 0f)); 22 | aabbs[3] = new AABB(new Point(5f, 5f, 5f), new Point(-5f, -5f, -5f)); 23 | 24 | bool[] results = new bool[] { 25 | false, true, true, true 26 | }; 27 | int t = 0; 28 | 29 | for (int i = 0; i < aabbs.Length; ++i) { 30 | if (Intersects.SphereAABBIntersect(aabbs[i], test) != results[t++]) { 31 | LogError("Expected aabb " + i + " to " + 32 | (results[t - 1] ? "intersect" : "not intersect") + 33 | " the sphere"); 34 | } 35 | } 36 | } 37 | 38 | public override void Render() { 39 | base.Render(); 40 | DrawOrigin(); 41 | 42 | for (int i = 0; i < aabbs.Length; ++i) { 43 | GL.Color3(0f, 0f, 1f); 44 | if (Intersects.SphereAABBIntersect(test, aabbs[i])) { 45 | GL.Color3(1f, 0f, 0f); 46 | } 47 | aabbs[i].Render(); 48 | } 49 | 50 | GL.Color3(0f, 0f, 1f); 51 | test.Render(); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/AABBPlaneIntersection.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class AABBPlaneIntersection : Application { 7 | Plane test = new Plane(); 8 | 9 | AABB[] aabbs = new AABB[] { 10 | null, null, null, null // Size = 4 11 | }; 12 | 13 | public override void Initialize(int width, int height) { 14 | GL.Enable(EnableCap.DepthTest); 15 | GL.Enable(EnableCap.CullFace); 16 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 17 | GL.PointSize(5f); 18 | 19 | test.Normal = new Vector3(0f, 1f, 0.5f); 20 | aabbs[0] = new AABB(new Point(-2f, -2f, -2f), new Point(-1f, -1f, -1f)); 21 | aabbs[1] = new AABB(new Point(2f, 1f, 2f), new Point(4f, 3f, 4f)); 22 | aabbs[2] = new AABB(new Point(1f, 0f, 1f), new Point(0f, -1f, 0f)); 23 | aabbs[3] = new AABB(new Point(5f, 5f, 5f), new Point(-5f, -5f, -5f)); 24 | 25 | bool[] results = new bool[] { 26 | false, false, true, true 27 | }; 28 | int t = 0; 29 | 30 | for (int i = 0; i < aabbs.Length; ++i) { 31 | if (Intersects.AABBPlaneIntersect(aabbs[i], test) != results[t++]) { 32 | LogError("Expected aabb " + i + " to " + 33 | (results[t - 1] ? "intersect" : "not intersect") + 34 | " the plane"); 35 | } 36 | } 37 | } 38 | 39 | public override void Render() { 40 | base.Render(); 41 | DrawOrigin(); 42 | 43 | for (int i = 0; i < aabbs.Length; ++i) { 44 | GL.Color3(0f, 0f, 1f); 45 | if (Intersects.AABBPlaneIntersect(test, aabbs[i])) { 46 | GL.Color3(1f, 0f, 0f); 47 | } 48 | aabbs[i].Render(); 49 | } 50 | 51 | GL.Color3(0f, 0f, 1f); 52 | test.Render(5f); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/TrianglePlaneIntersection.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class TrianglePlaneIntersection : Application { 7 | Plane plane = new Plane(new Point(5, 6, 7), new Point(6, 5, 4), new Point(1, 2, 3)); 8 | Triangle[] triangles = new Primitive.Triangle[] { 9 | new Triangle(new Point(-1.0f, 5.0f, 0.0f), new Point(2.0f, 2.0f, -3.0f), new Point(5.0f, 5.0f, 0.0f)), 10 | new Triangle(new Point(-1, -1, 0), new Point(0, 1, 0), new Point(1, -1, 0)), 11 | new Triangle(new Point(-1.0f, -5.0f, 0.0f), new Point(2.0f, -2.0f, -3.0f), new Point(5.0f, -5.0f, 0.0f)), 12 | new Triangle(new Point(5, 6, 7), new Point(6, 5, 4), new Point(1, 2, 3)), 13 | }; 14 | 15 | public override void Initialize(int width, int height) { 16 | GL.Enable(EnableCap.DepthTest); 17 | GL.PointSize(4f); 18 | GL.Disable(EnableCap.CullFace); 19 | 20 | bool[] expected = new bool[] { false, true, false, true }; 21 | for (int i = 0; i < triangles.Length; ++i) { 22 | bool result = Collisions.PlaneTriangleIntersection(plane, triangles[i]); 23 | if (result != expected[i]) { 24 | LogError("Expected triangle " + i + " to " + 25 | (expected[i] ? " intersect" : " NOT intersect") + 26 | " the plane"); 27 | } 28 | } 29 | } 30 | 31 | public override void Render() { 32 | base.Render(); 33 | DrawOrigin(); 34 | 35 | GL.Color3(0.0f, 0.0f, 1.0f); 36 | plane.Render(4); 37 | 38 | foreach (Triangle triangle in triangles) { 39 | if (Collisions.PlaneTriangleIntersection(triangle, plane)) { 40 | GL.Color3(0f, 1f, 0f); 41 | } 42 | else { 43 | GL.Color3(1f, 0f, 0f); 44 | } 45 | triangle.Render(); 46 | } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/TriangleTriangleIntersection.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class TriangleTriangleIntersection : Application { 7 | Triangle test = new Triangle(new Point(5, 6, 7), new Point(6, 5, 4), new Point(1, 2, 3)); 8 | Triangle[] triangles = new Primitive.Triangle[] { 9 | new Triangle(new Point(-1.0f, 5.0f, 0.0f), new Point(2.0f, 2.0f, -3.0f), new Point(5.0f, 5.0f, 0.0f)), 10 | new Triangle(new Point(-1, -1, 0), new Point(0, 1, 0), new Point(1, -1, 0)), 11 | new Triangle(new Point(-1.0f, -5.0f, 0.0f), new Point(2.0f, -2.0f, -3.0f), new Point(5.0f, -5.0f, 0.0f)), 12 | new Triangle(new Point(5, 6, 7), new Point(6, 5, 4), new Point(1, 2, 3)), 13 | }; 14 | 15 | public override void Initialize(int width, int height) { 16 | GL.Enable(EnableCap.DepthTest); 17 | GL.PointSize(4f); 18 | GL.Disable(EnableCap.CullFace); 19 | 20 | Vector3 center = test.p0.ToVector() + test.p1.ToVector() + test.p2.ToVector(); 21 | center *= 1.0f / 3.0f; 22 | 23 | test.p0.X -= center.X; 24 | test.p0.Y -= center.Y; 25 | test.p0.Z -= center.Z; 26 | 27 | test.p1.X -= center.X; 28 | test.p1.Y -= center.Y; 29 | test.p1.Z -= center.Z; 30 | 31 | test.p2.X -= center.X; 32 | test.p2.Y -= center.Y; 33 | test.p2.Z -= center.Z; 34 | } 35 | 36 | public override void Render() { 37 | base.Render(); 38 | DrawOrigin(); 39 | 40 | GL.Color3(0.0f, 0.0f, 1.0f); 41 | test.Render(); 42 | 43 | foreach (Triangle triangle in triangles) { 44 | if (Collisions.TriangleTriangleIntersection(triangle, test)) { 45 | GL.Color3(0f, 1f, 0f); 46 | } 47 | else { 48 | GL.Color3(1f, 0f, 0f); 49 | } 50 | triangle.Render(); 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Primitive/Point.cs: -------------------------------------------------------------------------------- 1 | using Math_Implementation; 2 | using OpenTK.Graphics.OpenGL; 3 | 4 | namespace CollisionDetectionSelector.Primitive { 5 | class Point { 6 | protected Vector3 position = new Vector3(); 7 | public Vector3 Position { 8 | get { 9 | return position; 10 | } 11 | set { 12 | position.X = value.X; 13 | position.Y = value.Y; 14 | position.Z = value.Z; 15 | } 16 | } 17 | public float X { 18 | get { 19 | return position.X; 20 | } 21 | set { 22 | position.X = value; 23 | } 24 | } 25 | public float Y { 26 | get { 27 | return position.Y; 28 | } 29 | set { 30 | position.Y = value; 31 | } 32 | } 33 | public float Z { 34 | get { 35 | return position.Z; 36 | } 37 | set { 38 | position.Z = value; 39 | } 40 | } 41 | public Point() { 42 | Position = new Vector3(); 43 | } 44 | public Point(float x, float y, float z) { 45 | Position = new Vector3(x, y, z); 46 | } 47 | public Point(Vector3 v) { 48 | Position = new Vector3(v.X, v.Y, v.Z); 49 | } 50 | public Point(Point v) { 51 | Position = new Vector3(v.X, v.Y, v.Z); 52 | } 53 | public void FromVector(Vector3 v) { 54 | Position = new Vector3(v.X, v.Y, v.Z); 55 | } 56 | public Vector3 ToVector() { 57 | return new Vector3(Position.X, Position.Y, Position.Z); 58 | } 59 | #region Rendering 60 | public void Render() { 61 | GL.Begin(PrimitiveType.Points); 62 | GL.Vertex3(Position.X, Position.Y, Position.Z); 63 | GL.End(); 64 | } 65 | public override string ToString() { 66 | return "(" + Position.X + ", " + Position.Y + ", " + Position.Z + ")"; 67 | } 68 | #endregion 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/SpherePlaneIntersection.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class SpherePlaneIntersection : Application { 7 | Sphere test = new Sphere(new Point(1f, 0f, 1f), 2f); 8 | 9 | Plane[] planes = new Plane[] { 10 | null, null, null, null, null // Size = 5 11 | }; 12 | 13 | public override void Initialize(int width, int height) { 14 | GL.Enable(EnableCap.DepthTest); 15 | GL.Enable(EnableCap.CullFace); 16 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 17 | GL.PointSize(5f); 18 | 19 | planes[0] = new Plane(); 20 | planes[1] = new Plane(new Vector3(0f, 1f, 0.2f), 3f); 21 | planes[2] = new Plane(new Vector3(0f, 1f, 0f), -2f); 22 | planes[3] = new Plane(new Vector3(-1f, 1f, 2f), 3f); 23 | planes[4] = new Plane(new Vector3(1f, 0f, 0f), 3f); 24 | 25 | bool[] results = new bool[] { 26 | true, false, true, false, true 27 | }; 28 | int t = 0; 29 | 30 | for (int i = 0; i < planes.Length; ++i) { 31 | if (Intersects.SpherePlaneIntersect(planes[i], test) != results[t++]) { 32 | LogError("Expected plane " + i + " to " + 33 | (results[t - 1] ? "intersect" : "not intersect") + 34 | " the sphere"); 35 | } 36 | } 37 | } 38 | 39 | public override void Render() { 40 | base.Render(); 41 | DrawOrigin(); 42 | 43 | GL.Disable(EnableCap.CullFace); 44 | for (int i = 0; i < planes.Length; ++i) { 45 | GL.Color3(0f, 0f, 1f); 46 | if (Intersects.SpherePlaneIntersect(test, planes[i])) { 47 | GL.Color3(1f, 0f, 0f); 48 | } 49 | planes[i].Render(); 50 | } 51 | GL.Enable(EnableCap.CullFace); 52 | 53 | GL.Color3(0f, 0f, 1f); 54 | test.Render(); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/AABBAABBIntersection.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class AABBtoAABBIntersection : Application { 7 | AABB[] aabbs = new AABB[] { 8 | null, null, null, null // Size = 4 9 | }; 10 | 11 | public override void Initialize(int width, int height) { 12 | GL.Enable(EnableCap.DepthTest); 13 | GL.Enable(EnableCap.CullFace); 14 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 15 | 16 | aabbs[0] = new AABB(new Point(-0.5f, -2f, -0.5f), new Point(0.5f, 2f, 0.5f)); 17 | aabbs[1] = new AABB(); 18 | aabbs[2] = new AABB(new Point(1f, 1f, 1f), new Point(3f, 3f, 3f)); 19 | aabbs[3] = new AABB(new Point(-3f, -3f, -3f), new Point(-4f, -4f, -4f)); 20 | 21 | bool[] results = new bool[] { 22 | true, true, false, false, true, true, true, false, false, 23 | true, true, false, false, false, false, true, 24 | }; 25 | int t = 0; 26 | 27 | for (int i = 0; i < aabbs.Length; ++i) { 28 | for (int j = 0; j < aabbs.Length; ++j) { 29 | if (Intersects.AABBAABBIntersect(aabbs[i], aabbs[j]) != results[t++]) { 30 | LogError("aabb " + i + " and " + j + " should " + 31 | (results[t - 1] ? "" : "not ") + "intersect" 32 | ); 33 | } 34 | } 35 | } 36 | } 37 | 38 | public override void Render() { 39 | base.Render(); 40 | DrawOrigin(); 41 | 42 | for (int i = 0; i < aabbs.Length; ++i) { 43 | GL.Color3(0f, 0f, 1f); 44 | for (int j = 0; j < aabbs.Length; ++j) { 45 | if (i != j && Intersects.AABBAABBIntersect(aabbs[i], aabbs[j])) { 46 | GL.Color3(1f, 0f, 0f); 47 | break; 48 | } 49 | } 50 | aabbs[i].Render(); 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/SphereSphereIntersection.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class SphereSphereIntersection : Application { 7 | Sphere[] spheres = new Sphere[] { 8 | null, null, null, null // Size = 4 9 | }; 10 | 11 | public override void Initialize(int width, int height) { 12 | GL.Enable(EnableCap.DepthTest); 13 | GL.Enable(EnableCap.CullFace); 14 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 15 | 16 | spheres[0] = new Sphere(new Point(0f, 0f, 0f), 2f); 17 | spheres[1] = new Sphere(new Point(0f, 3.5f, 0f), 1f); 18 | spheres[2] = new Sphere(new Point(0f, -3f, 0f), 1f); 19 | spheres[3] = new Sphere(new Point(1f, 0f, 0f), 1f); 20 | 21 | bool[] results = new bool[] { 22 | true, false, true, true, false, true, false, false, true, 23 | false, true, false, true, false, false, true 24 | }; 25 | int t = 0; 26 | 27 | for (int i = 0; i < spheres.Length; ++i) { 28 | for (int j = 0; j < spheres.Length; ++j) { 29 | if (Intersects.SphereSphereIntersect(spheres[i], spheres[j]) != results[t++]) { 30 | LogError("sphere " + i + " and " + j + " should " + 31 | (results[t - 1] ? "" : "not ") + "intersect" 32 | ); 33 | } 34 | } 35 | } 36 | } 37 | 38 | public override void Render() { 39 | base.Render(); 40 | DrawOrigin(); 41 | 42 | for (int i = 0; i < spheres.Length; ++i) { 43 | GL.Color3(0f, 0f, 1f); 44 | for (int j = 0; j < spheres.Length; ++j) { 45 | if (i != j && Intersects.SphereSphereIntersect(spheres[i], spheres[j])) { 46 | GL.Color3(1f, 0f, 0f); 47 | break; 48 | } 49 | } 50 | spheres[i].Render(); 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/RaycastAABB.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class RaycastAABB : Application { 7 | public AABB test = new AABB(new Point(0.5f, 0.5f, 0.5f), new Point(2f, 2f, 2f)); 8 | 9 | public Ray[] rays = new Ray[] { 10 | new Ray(new Point(-2, -2, -2), new Vector3(2, 2, 2)), 11 | new Ray(new Point(0f, 0f, 0f), new Vector3(0f, 1f, 0f)), 12 | new Ray(new Point(0f, 0f, 0f), new Vector3(-1f, 0f, 0f)), 13 | new Ray(new Point(1f, 1f, 1f), new Vector3(1f, 1f, 0f)), 14 | new Ray(new Point(0.4f, 1f, 1f), new Vector3(-1f, 0f, 0f)), 15 | }; 16 | 17 | public override void Initialize(int width, int height) { 18 | GL.Enable(EnableCap.DepthTest); 19 | GL.PointSize(5f); 20 | GL.Enable(EnableCap.CullFace); 21 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 22 | 23 | bool[] results = new bool[] { 24 | true, false, false, true, false 25 | }; 26 | 27 | float t; 28 | for (int i = 0; i < results.Length; ++i) { 29 | if (LinesAndRays.RaycastAABB(rays[i], test, out t) != results[i]) { 30 | LogError("Expected ray at index: " + i + " to " + 31 | (results[i] ? "intersect" : "not intersect") + 32 | " the aabb"); 33 | } 34 | } 35 | } 36 | 37 | public override void Render() { 38 | base.Render(); 39 | DrawOrigin(); 40 | 41 | GL.Color3(0f, 1f, 0f); 42 | test.Render(); 43 | 44 | float t; 45 | foreach (Ray ray in rays) { 46 | if (LinesAndRays.RaycastAABB(ray, test, out t)) { 47 | GL.Color3(1f, 0f, 0f); 48 | } 49 | else { 50 | GL.Color3(0f, 0f, 1f); 51 | } 52 | ray.Render(); 53 | } 54 | } 55 | 56 | private void Log(string s) { 57 | System.Console.WriteLine(s); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/LinecastSphere.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class LinecastSphere : Application { 7 | public Line[] lines = new Line[] { 8 | new Line(new Point(2.5f, 2.5f, 2.5f), new Point(4, 4, 4)), // false 9 | new Line(new Point(1f, 1f, 0f), new Point(0f, 0f, 0f)), // false 10 | new Line(new Point(-1f, -1f, 0f), new Point(-3f, 0f, 0f)), // true 11 | }; 12 | public Sphere sphere = new Sphere(); 13 | 14 | public override void Initialize(int width, int height) { 15 | GL.Enable(EnableCap.DepthTest); 16 | GL.PointSize(5f); 17 | GL.Enable(EnableCap.CullFace); 18 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 19 | 20 | sphere.Position = new Point(0f, 0f, 0f); 21 | sphere.Radius = 2; 22 | 23 | bool[] results = new bool[] { false, false, true }; 24 | Point result = new Point(); 25 | for (int i = 0; i < results.Length; ++i) { 26 | if (LinesAndRays.LinecastSphere(lines[i], sphere, out result) != results[i]) { 27 | LogError("Line at index " + i + " was " + 28 | (results[i] ? "expected" : "not expected") + 29 | "to intersect the test SPHERE"); 30 | } 31 | } 32 | } 33 | 34 | public override void Render() { 35 | base.Render(); 36 | DrawOrigin(); 37 | 38 | Point result = new Point(); 39 | foreach (Line line in lines) { 40 | if (LinesAndRays.LinecastSphere(line, sphere, out result)) { 41 | GL.Color3(1f, 0f, 1f); 42 | result.Render(); 43 | GL.Color3(0f, 2f, 0f); 44 | } 45 | else { 46 | GL.Color3(1f, 0f, 0f); 47 | } 48 | line.Render(); 49 | } 50 | 51 | GL.Color3(0f, 0f, 1f); 52 | sphere.Render(); 53 | } 54 | 55 | private void Log(string s) { 56 | System.Console.WriteLine(s); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/TriangleAABBIntersection.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class TriangleAABBIntersection : Application { 7 | AABB[] aabbs = new AABB[] { 8 | new AABB(new Point(2, 4, -1), new Vector3(0.5f, 0.5f, 0.5f)), 9 | new AABB(new Point(-1.0f, 5.0f, 0.0f), new Vector3(0.5f, 0.5f, 0.5f)), 10 | new AABB(new Point(0.0f, 0.0f, 0.0f), new Vector3(5f, 7f, 5f)), 11 | new AABB( new Point(2.0f, 3.0f, -3.0f), new Vector3(3f, 0.5f, 2f)), 12 | 13 | 14 | new AABB(new Point(2f, 2f, 2f), new Vector3(1.0f, 1.0f, 1.0f)), 15 | new AABB(new Point(-2f, -2f, -2f), new Vector3(1.0f, 1.0f, 1.0f)) 16 | }; 17 | 18 | Triangle triangle = new Triangle(new Point(-1.0f, 5.0f, 0.0f), new Point(2.0f, 2.0f, -3.0f), new Point(5.0f, 5.0f, 0.0f)); 19 | 20 | public override void Initialize(int width, int height) { 21 | GL.Enable(EnableCap.DepthTest); 22 | GL.PointSize(4f); 23 | GL.Disable(EnableCap.CullFace); 24 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 25 | 26 | bool[] expected = new bool[] { true, true, true, true, false, false }; 27 | for (int i = 0; i < aabbs.Length; ++i) { 28 | bool result = Collisions.TriangleAABBIntersect(triangle, aabbs[i]); 29 | if (result != expected[i]) { 30 | LogError("Expected aabb " + i + " to " + 31 | (expected[i] ? " intersect" : " NOT intersect") + 32 | " the triangle"); 33 | } 34 | } 35 | } 36 | 37 | public override void Render() { 38 | base.Render(); 39 | DrawOrigin(); 40 | 41 | GL.Color3(0.0f, 0.0f, 1.0f); 42 | triangle.Render(); 43 | 44 | foreach (AABB aabb in aabbs) { 45 | if (Collisions.TriangleAABBIntersect(triangle, aabb)) { 46 | GL.Color3(0f, 1f, 0f); 47 | } 48 | else { 49 | GL.Color3(1f, 0f, 0f); 50 | } 51 | aabb.Render(); 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/LinecastAABB.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class LinecastAABB : Application { 7 | public Line[] lines = new Line[] { 8 | new Line(new Point(2.5f, 2.5f, 2.5f), new Point(4, 4, 4)), // false 9 | new Line(new Point(1f, 1f, 0f), new Point(0f, 0f, 0f)), // false 10 | new Line(new Point(-1f, -1f, 0f), new Point(-3f, 0f, 0f)), // true 11 | new Line(new Point(-5f, 0f, 0f), new Point(5f, 0f, 0f)) // true 12 | }; 13 | public AABB aabb = new AABB(); 14 | 15 | public override void Initialize(int width, int height) { 16 | GL.Enable(EnableCap.DepthTest); 17 | GL.PointSize(5f); 18 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 19 | 20 | aabb.Max = new Point(2, 2, 2); 21 | aabb.Min = new Point(-2, -2, -2); 22 | 23 | bool[] results = new bool[] { false, false, true, true }; 24 | Point result = new Point(); 25 | for (int i = 0; i < results.Length; ++i) { 26 | if (LinesAndRays.LinecastAABB(lines[i], aabb, out result) != results[i]) { 27 | LogError("Line at index " + i + " was " + 28 | (results[i] ? " expected" : " not expected") + 29 | " to intersect the test aabb"); 30 | } 31 | } 32 | } 33 | 34 | public override void Render() { 35 | base.Render(); 36 | DrawOrigin(); 37 | 38 | Point result = new Point(); 39 | foreach (Line line in lines) { 40 | if (LinesAndRays.LinecastAABB(line, aabb, out result)) { 41 | GL.Color3(1f, 0f, 1f); 42 | result.Render(); 43 | GL.Color3(0f, 2f, 0f); 44 | } 45 | else { 46 | GL.Color3(1f, 0f, 0f); 47 | } 48 | line.Render(); 49 | } 50 | 51 | GL.Color3(0f, 0f, 1f); 52 | aabb.Render(); 53 | } 54 | 55 | private void Log(string s) { 56 | System.Console.WriteLine(s); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/LinecastPlane.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class LinecastPlane : Application { 7 | public Line[] lines = new Line[] { 8 | new Line(new Point(2.5f, 2.5f, 2.5f), new Point(4, 4, 4)), // false 9 | new Line(new Point(1f, 1f, 0f), new Point(0f, 0f, 0f)), // false 10 | new Line(new Point(-1f, -1f, 0f), new Point(-3f, 0f, 0f)), // false 11 | new Line(new Point(-5f, 0f, 0f), new Point(5f, 0f, 0f)), // true 12 | new Line(new Point(7f, 0f, 1f), new Point(-7f, 0f, 1f)), // true 13 | new Line(new Point(0.5f, 0.5f, 0.5f), new Point(0.5f, 0.5f, 2f)) // false 14 | }; 15 | public Plane plane = new Plane(); 16 | 17 | public override void Initialize(int width, int height) { 18 | GL.Enable(EnableCap.DepthTest); 19 | GL.PointSize(5f); 20 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 21 | 22 | plane.Normal = new Vector3(1, 1, 0); 23 | plane.Distance = 1; 24 | 25 | bool[] results = new bool[] { false, true, false, false, true, false }; 26 | Point result = new Point(); 27 | for (int i = 0; i < results.Length; ++i) { 28 | if (LinesAndRays.LinecastPlane(lines[i], plane, out result) != results[i]) { 29 | LogError("Line at index " + i + " was " + 30 | (results[i] ? "expected" : "not expected") + 31 | "to intersect the test plane"); 32 | } 33 | } 34 | } 35 | 36 | public override void Render() { 37 | base.Render(); 38 | DrawOrigin(); 39 | 40 | Point result = new Point(); 41 | foreach (Line line in lines) { 42 | if (LinesAndRays.LinecastPlane(line, plane, out result)) { 43 | GL.Color3(1f, 0f, 1f); 44 | result.Render(); 45 | GL.Color3(0f, 2f, 0f); 46 | } 47 | else { 48 | GL.Color3(1f, 0f, 0f); 49 | } 50 | line.Render(); 51 | } 52 | 53 | GL.Color3(0f, 0f, 1f); 54 | plane.Render(5f); 55 | } 56 | 57 | private void Log(string s) { 58 | System.Console.WriteLine(s); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/OBJDebugTrianglesAABB.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | using CollisionDetectionSelector; 5 | 6 | namespace CollisionDetectionSelector.Samples { 7 | class OBJDebugTrianglesAABB : Application { 8 | OBJLoader obj = null; 9 | 10 | public override void Initialize(int width, int height) { 11 | GL.Enable(EnableCap.DepthTest); 12 | GL.Enable(EnableCap.CullFace); 13 | GL.Enable(EnableCap.Lighting); 14 | GL.Enable(EnableCap.Light0); 15 | 16 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 17 | 18 | GL.Light(LightName.Light0, LightParameter.Position, new float[] { 0.0f, 0.5f, 0.5f, 0.0f }); 19 | GL.Light(LightName.Light0, LightParameter.Ambient, new float[] { 0f, 1f, 0f, 1f }); 20 | GL.Light(LightName.Light0, LightParameter.Diffuse, new float[] { 0f, 1f, 0f, 1f }); 21 | GL.Light(LightName.Light0, LightParameter.Specular, new float[] { 1f, 1f, 1f, 1f }); 22 | 23 | obj = new OBJLoader("Assets/suzanne.obj"); 24 | 25 | if (obj.NumCollisionTriangles != 968) { 26 | LogError("Suzanne triangle count expected at 968, got: " + obj.NumCollisionTriangles); 27 | } 28 | AABB test = new AABB(new Point(-1.367188f, -0.984375f, -0.851562f), new Point(1.367188f, 0.984375f, 0.851562f)); 29 | if (!AlmostEqual(test, obj.BoundingBox)) { 30 | LogError("Expected bounting box:\n" + test.ToString() + "\n Got bounding box: \n" + obj.BoundingBox.ToString()); 31 | } 32 | } 33 | 34 | private bool AlmostEqual(float f1, float f2) { 35 | return (System.Math.Abs(f1 - f2) <= float.Epsilon * 36 | System.Math.Max(1.0f, System.Math.Max( 37 | System.Math.Abs(f1), System.Math.Abs(f2)))); 38 | } 39 | 40 | private bool AlmostEqual(Point p1, Point p2) { 41 | return AlmostEqual(p1.X, p2.X) && AlmostEqual(p1.Y, p2.Y) && AlmostEqual(p1.Z, p2.Z); 42 | } 43 | 44 | private bool AlmostEqual(AABB aabb1, AABB aabb2) { 45 | return AlmostEqual(aabb1.Min, aabb2.Min) && AlmostEqual(aabb1.Max, aabb2.Max); 46 | } 47 | 48 | public override void Render() { 49 | base.Render(); 50 | DrawOrigin(); 51 | 52 | GL.PushMatrix(); 53 | GL.Scale(3.0f, 3.0f, 3.0f); 54 | obj.DebugRender(); 55 | GL.PopMatrix(); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/RaycastPlane.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class RaycastPlane : Application { 7 | public Plane test = new Plane(new Vector3(1f, 1f, 0f), 1f); 8 | 9 | public Ray[] rays = new Ray[] { 10 | new Ray(new Point(0f, 0f, 0f), new Vector3(0f, -1f, 0f)), 11 | new Ray(new Point(0.5f, 0.5f, 0f), new Vector3(-1f, -1f, 0f)), 12 | new Ray(new Point(1f, 1f, 0f), new Vector3(1f, 1f, 0f)), 13 | new Ray(new Point(1f, 1f, -3f), new Vector3(0f, 0f, 1f)), 14 | new Ray(new Point(2f, 2f, 3f), new Vector3(0f, -1f, 0f)), 15 | new Ray(new Point(3f, 3f, 3f), new Vector3(-3f, -3f, -3f)), 16 | new Ray(new Point(1f, 1f, 3f), new Vector3(-2f, -3f, 1f)), 17 | }; 18 | 19 | public override void Initialize(int width, int height) { 20 | GL.Enable(EnableCap.DepthTest); 21 | GL.PointSize(5f); 22 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); 23 | 24 | bool[] results = new bool[] { 25 | false, false, false, false, true, true, true 26 | }; 27 | 28 | float t; 29 | for (int i = 0; i < results.Length; ++i) { 30 | if (LinesAndRays.RaycastPlane(rays[i], test, out t) != results[i]) { 31 | LogError("Expected ray at index: " + i + " to " + 32 | (results[i] ? "intersect" : "not intersect") + 33 | " the plane"); 34 | } 35 | } 36 | } 37 | 38 | public override void Render() { 39 | base.Render(); 40 | DrawOrigin(); 41 | 42 | GL.Color3(1f, 1f, 1f); 43 | test.Render(5f); 44 | 45 | 46 | float t; 47 | foreach (Ray ray in rays) { 48 | if (LinesAndRays.RaycastPlane(ray, test, out t)) { 49 | Point colPoint = new Point(); 50 | LinesAndRays.RaycastPlane(ray, test, out colPoint); 51 | GL.Color3(0f, 1f, 0f); 52 | colPoint.Render(); 53 | GL.Color3(1f, 0f, 0f); 54 | } 55 | else { 56 | GL.Color3(0f, 0f, 1f); 57 | } 58 | ray.Render(); 59 | } 60 | } 61 | 62 | private void Log(string s) { 63 | System.Console.WriteLine(s); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Primitive/LinetestTriangle.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class LinetestTriangle : Application { 7 | public Line[] lines = new Line[] { 8 | new Line(new Point(2.5f, 2.5f, 2.5f), new Point(4, 4, 4)), 9 | new Line(new Point(1f, 1f, 0f), new Point(0f, 0f, 0f)), 10 | new Line(new Point(-1f, -1f, 0f), new Point(-3f, 0f, 0f)), 11 | new Line(new Point(-5f, 0f, 0f), new Point(5f, 0f, 0f)), 12 | new Line(new Point(7f, 0f, 1f), new Point(-7f, 0f, 1f)), 13 | new Line(new Point(0.5f, 0.5f, 0.5f), new Point(0.5f, 0.5f, 2f)) 14 | }; 15 | Triangle triangle = new Triangle(new Point(5.207108f, -1.792894f, -3.949748f), 16 | new Point(5.207108f, -1.792894f, 5.949748f), 17 | new Point(-1.792894f, 5.207108f, 1)); 18 | 19 | 20 | public override void Initialize(int width, int height) { 21 | GL.Enable(EnableCap.DepthTest); 22 | GL.PointSize(5f); 23 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 24 | 25 | bool[] results = new bool[] { false, false, false, true, true, false }; 26 | Point result = new Point(); 27 | for (int i = 0; i < results.Length; ++i) { 28 | if (Collisions.LinecastTriangle(lines[i], triangle, out result) != results[i]) { 29 | LogError("Line at index " + i + " was " + 30 | (results[i] ? "expected" : "not expected") + 31 | "to intersect the test triangle"); 32 | } 33 | } 34 | } 35 | 36 | public override void Render() { 37 | base.Render(); 38 | DrawOrigin(); 39 | 40 | Point result = new Point(); 41 | foreach (Line line in lines) { 42 | if (Collisions.LinecastTriangle(line, triangle, out result)) { 43 | GL.Color3(1f, 0f, 1f); 44 | result.Render(); 45 | GL.Color3(0f, 2f, 0f); 46 | } 47 | else { 48 | GL.Color3(1f, 0f, 0f); 49 | } 50 | line.Render(); 51 | } 52 | 53 | GL.Color3(0f, 0f, 1f); 54 | triangle.Render(); 55 | } 56 | 57 | private void Log(string s) { 58 | System.Console.WriteLine(s); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | class Program { 4 | static void Main(string[] args) { 5 | System.Type[] samples = FindAndPrintApplicationChildClasses(); 6 | System.Type selectedSampleType = null; 7 | 8 | if (samples == null || samples.Length == 0) { 9 | System.Console.WriteLine("No samples found, press any key to quit"); 10 | System.Console.ReadKey(); 11 | return; 12 | } 13 | 14 | if (args.Length > 0) { 15 | selectedSampleType = ParseSampleFromNumber(samples, args[0]); 16 | } 17 | 18 | System.Console.WriteLine("Select a sample, or q to quit"); 19 | while (selectedSampleType == null) { 20 | System.Console.Write("Enter a sample number: ", System.ConsoleColor.White); 21 | string input = System.Console.ReadLine(); 22 | if (!string.IsNullOrEmpty(input) && input.ToLower()[0] == 'q') { 23 | return; 24 | } 25 | selectedSampleType = ParseSampleFromNumber(samples, input); 26 | } 27 | 28 | Application game = (Application)System.Activator.CreateInstance(selectedSampleType); 29 | game.Main(args); 30 | } 31 | 32 | static System.Type[] FindAndPrintApplicationChildClasses() { 33 | System.Type[] samples = typeof(Application).Assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(Application)) && t != typeof(Application)).ToArray(); 34 | int blockSize = samples.Length / 2; 35 | for (int i = 0; i < blockSize; i++) { 36 | System.Console.WriteLine(string.Format("{2,2}. {0,-30}{3,2}. {1,-30}", samples[i].Name, samples[i + blockSize].Name, i, i + blockSize), System.ConsoleColor.DarkGray); 37 | 38 | } 39 | if (blockSize * 2 < samples.Length) { 40 | System.Console.WriteLine($"{samples.Length - 1,36}. {samples[samples.Length - 1].Name}", System.ConsoleColor.DarkGray); 41 | } 42 | if (samples.Length != 0) { 43 | System.Console.WriteLine(); 44 | } 45 | 46 | return samples; 47 | } 48 | 49 | static System.Type ParseSampleFromNumber(System.Type[] samples, string input) { 50 | int number; 51 | if (!int.TryParse(input, out number)) { 52 | System.Console.WriteLine("Invalid format.", System.ConsoleColor.Red); 53 | return null; 54 | } 55 | 56 | if (number >= samples.Length || number < 0) { 57 | System.Console.WriteLine("Invalid number.", System.ConsoleColor.Red); 58 | return null; 59 | } 60 | 61 | return samples[number]; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/RaycastTriangle.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class RaycastTriangle : Application { 7 | Triangle test = new Triangle(new Point(5.207108f, -1.792894f, -3.949748f), 8 | new Point(5.207108f, -1.792894f, 5.949748f), 9 | new Point(-1.792894f, 5.207108f, 1)); 10 | 11 | 12 | 13 | public Ray[] rays = new Ray[] { 14 | new Ray(new Point(0f, 0f, 0f), new Vector3(0f, -1f, 0f)), 15 | new Ray(new Point(0.5f, 0.5f, 0f), new Vector3(-1f, -1f, 0f)), 16 | new Ray(new Point(1f, 1f, 0f), new Vector3(1f, 1f, 0f)), 17 | new Ray(new Point(1f, 1f, -3f), new Vector3(0f, 0f, 1f)), 18 | new Ray(new Point(2f, 2f, 3f), new Vector3(0f, -1f, 0f)), 19 | new Ray(new Point(3f, 3f, 3f), new Vector3(-3f, -3f, -3f)), 20 | new Ray(new Point(1f, 1f, 3f), new Vector3(-2f, -3f, 1f)), 21 | }; 22 | 23 | public override void Initialize(int width, int height) { 24 | GL.Enable(EnableCap.DepthTest); 25 | GL.PointSize(5f); 26 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); 27 | 28 | bool[] results = new bool[] { 29 | false, false, true, false, true, true, false 30 | }; 31 | 32 | float t; 33 | for (int i = 0; i < results.Length; ++i) { 34 | if (Collisions.RaycastTriangle(rays[i], test, out t) != results[i]) { 35 | LogError("Expected ray at index: " + i + " to " + 36 | (results[i] ? "intersect" : "not intersect") + 37 | " the triangle"); 38 | } 39 | } 40 | } 41 | 42 | public override void Render() { 43 | base.Render(); 44 | DrawOrigin(); 45 | 46 | GL.Color3(1f, 1f, 1f); 47 | test.Render(); 48 | 49 | 50 | float t; 51 | foreach (Ray ray in rays) { 52 | if (Collisions.RaycastTriangle(ray, test, out t)) { 53 | Point colPoint = new Point(); 54 | Collisions.RaycastTriangle(ray, test, out colPoint); 55 | GL.Color3(0f, 1f, 0f); 56 | colPoint.Render(); 57 | GL.Color3(1f, 0f, 0f); 58 | } 59 | else { 60 | GL.Color3(0f, 0f, 1f); 61 | } 62 | ray.Render(); 63 | } 64 | } 65 | 66 | private void Log(string s) { 67 | System.Console.WriteLine(s); 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/ClosestPointTriangle.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class ClosestPointTriangle : Application { 7 | protected Point[] points = new Point[] { 8 | new Point(1f, 1f, 1f), 9 | new Point(-1f, -3f, -4f), 10 | new Point(2, 4, -1), 11 | new Point(-2.732051f, 6.732051f, 1.732051f), 12 | new Point(3, 7, -4) 13 | }; 14 | Point[] tests = new Point[] { 15 | new Point(1, 3.5f, -1.5f), 16 | new Point(2, 2, -3), 17 | new Point(2, 4, -1), 18 | new Point(-1, 5, 0), 19 | new Point(3, 4, -0.9999995f), 20 | }; 21 | 22 | Triangle triangle = new Triangle(new Point(-1.0f, 5.0f, 0.0f), new Point(2.0f, 2.0f, -3.0f), new Point(5.0f, 5.0f, 0.0f)); 23 | 24 | public override void Initialize(int width, int height) { 25 | GL.Enable(EnableCap.DepthTest); 26 | GL.PointSize(4f); 27 | GL.Disable(EnableCap.CullFace); 28 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 29 | 30 | for (int i = 0; i < points.Length; ++i) { 31 | Point c = Collisions.ClosestPointTriangle(triangle, points[i]); 32 | if (!PointCompare(c, tests[i])) { 33 | LogError("Expected point " + i + " to be: " + tests[i] + ", got: " + c); 34 | } 35 | } 36 | } 37 | 38 | protected bool PointCompare(Point p1, Point p2) { 39 | float epsilon = 0.00001f; 40 | 41 | float x = System.Math.Abs(p1.X - p2.X); 42 | float y = System.Math.Abs(p1.Y - p2.Y); 43 | float z = System.Math.Abs(p1.Z - p2.Z); 44 | 45 | if (x > epsilon) return false; 46 | if (y > epsilon) return false; 47 | if (z > epsilon) return false; 48 | return true; 49 | } 50 | 51 | public override void Render() { 52 | base.Render(); 53 | DrawOrigin(); 54 | 55 | GL.Color3(0.0f, 0.0f, 1.0f); 56 | triangle.Render(); 57 | 58 | GL.Color3(1.0f, 0.0f, 0.0f); 59 | GL.Begin(PrimitiveType.Lines); 60 | for (int i = 0; i < points.Length; ++i) { 61 | Point closest = Collisions.ClosestPointTriangle(triangle, points[i]); 62 | GL.Vertex3(points[i].X, points[i].Y, points[i].Z); 63 | GL.Vertex3(closest.X, closest.Y, closest.Z); 64 | } 65 | GL.End(); 66 | 67 | GL.Color3(0.0f, 1.0f, 0.0f); 68 | foreach (Point point in points) { 69 | point.Render(); 70 | } 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/OBJRaycast.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | using CollisionDetectionSelector; 5 | 6 | namespace CollisionDetectionSelector.Samples { 7 | class OBJRaycast : Application { 8 | OBJLoader loader = null; 9 | OBJ[] objs = new OBJ[] { null, null, null }; 10 | 11 | Ray[] tests = new Ray[] { 12 | new Ray(new Point(-1f, -1f, -1f), new Vector3(1f, 1f, 1f)), 13 | new Ray(new Point(-2f, 1f, 1f), new Vector3(0f, 1f, 0f)) 14 | }; 15 | 16 | public override void Initialize(int width, int height) { 17 | GL.Enable(EnableCap.DepthTest); 18 | GL.Enable(EnableCap.CullFace); 19 | GL.Enable(EnableCap.Lighting); 20 | GL.Enable(EnableCap.Light0); 21 | 22 | GL.Light(LightName.Light0, LightParameter.Position, new float[] { 0.0f, 0.5f, 0.5f, 0.0f }); 23 | GL.Light(LightName.Light0, LightParameter.Ambient, new float[] { 0f, 1f, 0f, 1f }); 24 | GL.Light(LightName.Light0, LightParameter.Diffuse, new float[] { 0f, 1f, 0f, 1f }); 25 | GL.Light(LightName.Light0, LightParameter.Specular, new float[] { 1f, 1f, 1f, 1f }); 26 | 27 | loader = new OBJLoader("Assets/suzanne.obj"); 28 | objs[0] = new OBJ(loader); 29 | objs[1] = new OBJ(loader); 30 | objs[2] = new OBJ(loader); 31 | 32 | objs[1].Position = new Vector3(6.0f, 6.0f, 6.0f); 33 | objs[1].Scale = new Vector3(1.5f, 1.5f, 1.5f); 34 | 35 | objs[2].Position = new Vector3(-6.0f, -6.0f, -6.0f); 36 | objs[1].Scale = new Vector3(1.5f, 1.5f, 1.5f); 37 | objs[2].Rotation = new Vector3(90.0f, 0.0f, 0.0f); 38 | } 39 | 40 | public override void Render() { 41 | GL.Disable(EnableCap.Lighting); 42 | base.Render(); 43 | DrawOrigin(); 44 | GL.Enable(EnableCap.Lighting); 45 | 46 | GL.Color3(0f, 0f, 1f); 47 | foreach (OBJ obj in objs) { 48 | obj.Render(); 49 | } 50 | 51 | GL.Disable(EnableCap.Lighting); 52 | GL.Disable(EnableCap.CullFace); 53 | float t = 0; 54 | foreach (Ray test in tests) { 55 | bool intersection = false; 56 | foreach (OBJ obj in objs) { 57 | if (Intersects.OBJRaycast(test, obj, out t)) { 58 | intersection = true; 59 | } 60 | } 61 | if (intersection) { 62 | GL.Color3(0f, 1f, 0f); 63 | } 64 | else { 65 | GL.Color3(1f, 0f, 0f); 66 | } 67 | test.Render(); 68 | } 69 | GL.Enable(EnableCap.CullFace); 70 | GL.Enable(EnableCap.Lighting); 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/OBJSphereIntersection.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | using CollisionDetectionSelector; 5 | 6 | namespace CollisionDetectionSelector.Samples { 7 | class OBJSphereIntersection : Application { 8 | OBJLoader loader = null; 9 | OBJ[] objs = new OBJ[] { null, null, null }; 10 | 11 | Sphere[] tests = new Sphere[] { 12 | new Sphere(4f, 4f, 4f, 2f), 13 | new Sphere(-4f, -4f, -4f,3f), 14 | new Sphere(1f, 1f, 1f, 2f), 15 | new Sphere(2f, 2f, 2f, 1f), 16 | }; 17 | 18 | public override void Initialize(int width, int height) { 19 | GL.Enable(EnableCap.DepthTest); 20 | GL.Enable(EnableCap.CullFace); 21 | GL.Enable(EnableCap.Lighting); 22 | GL.Enable(EnableCap.Light0); 23 | 24 | GL.Light(LightName.Light0, LightParameter.Position, new float[] { 0.0f, 0.5f, 0.5f, 0.0f }); 25 | GL.Light(LightName.Light0, LightParameter.Ambient, new float[] { 0f, 1f, 0f, 1f }); 26 | GL.Light(LightName.Light0, LightParameter.Diffuse, new float[] { 0f, 1f, 0f, 1f }); 27 | GL.Light(LightName.Light0, LightParameter.Specular, new float[] { 1f, 1f, 1f, 1f }); 28 | 29 | loader = new OBJLoader("Assets/suzanne.obj"); 30 | objs[0] = new OBJ(loader); 31 | objs[1] = new OBJ(loader); 32 | objs[2] = new OBJ(loader); 33 | 34 | objs[1].Position = new Vector3(6.0f, 6.0f, 6.0f); 35 | objs[1].Scale = new Vector3(1.5f, 1.5f, 1.5f); 36 | 37 | objs[2].Position = new Vector3(-6.0f, -6.0f, -6.0f); 38 | objs[1].Scale = new Vector3(1.5f, 1.5f, 1.5f); 39 | objs[2].Rotation = new Vector3(90.0f, 0.0f, 0.0f); 40 | } 41 | 42 | public override void Render() { 43 | GL.Disable(EnableCap.Lighting); 44 | base.Render(); 45 | DrawOrigin(); 46 | GL.Enable(EnableCap.Lighting); 47 | 48 | GL.Color3(0f, 0f, 1f); 49 | foreach (OBJ obj in objs) { 50 | obj.Render(); 51 | } 52 | 53 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 54 | GL.Disable(EnableCap.Lighting); 55 | foreach (Sphere test in tests) { 56 | bool intersection = false; 57 | foreach (OBJ obj in objs) { 58 | if (Intersects.OBJSphereIntersect(test, obj)) { 59 | intersection = true; 60 | } 61 | } 62 | if (intersection) { 63 | GL.Color3(0f, 1f, 0f); 64 | } 65 | else { 66 | GL.Color3(1f, 0f, 0f); 67 | } 68 | test.Render(); 69 | } 70 | GL.Enable(EnableCap.Lighting); 71 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/OBJTrianglesSphere.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | using CollisionDetectionSelector; 5 | 6 | namespace CollisionDetectionSelector.Samples { 7 | class OBJDebugTrianglesSphere : Application { 8 | OBJLoader obj = null; 9 | 10 | public override void Initialize(int width, int height) { 11 | GL.Enable(EnableCap.DepthTest); 12 | GL.Enable(EnableCap.CullFace); 13 | GL.Enable(EnableCap.Lighting); 14 | GL.Enable(EnableCap.Light0); 15 | 16 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 17 | 18 | GL.Light(LightName.Light0, LightParameter.Position, new float[] { 0.0f, 0.5f, 0.5f, 0.0f }); 19 | GL.Light(LightName.Light0, LightParameter.Ambient, new float[] { 0f, 1f, 0f, 1f }); 20 | GL.Light(LightName.Light0, LightParameter.Diffuse, new float[] { 0f, 1f, 0f, 1f }); 21 | GL.Light(LightName.Light0, LightParameter.Specular, new float[] { 1f, 1f, 1f, 1f }); 22 | 23 | obj = new OBJLoader("Assets/suzanne.obj"); 24 | 25 | if (obj.NumCollisionTriangles != 968) { 26 | LogError("Suzanne triangle count expected at 968, got: " + obj.NumCollisionTriangles); 27 | } 28 | AABB test = new AABB(new Point(-1.367188f, -0.984375f, -0.851562f), new Point(1.367188f, 0.984375f, 0.851562f)); 29 | if (!AlmostEqual(test, obj.BoundingBox)) { 30 | LogError("Expected bounting box:\n" + test.ToString() + "\n Got bounding box: \n" + obj.BoundingBox.ToString()); 31 | } 32 | 33 | if (!AlmostEqual(obj.BoundingSphere.Radius, 1.887685f)) { 34 | LogError("Expected bounding sphere radius to be: 1.887685f, got: " + obj.BoundingSphere.Radius.ToString()); 35 | } 36 | 37 | if (!AlmostEqual(obj.BoundingSphere.Position, new Point(0f, 0f, 0f))) { 38 | LogError("Expected bounding sphere radius to be: (0, 0, 0), got: " + obj.BoundingSphere.Position.ToString()); 39 | } 40 | } 41 | 42 | private bool AlmostEqual(float f1, float f2) { 43 | return (System.Math.Abs(f1 - f2) <= 0.00001f * 44 | System.Math.Max(1.0f, System.Math.Max( 45 | System.Math.Abs(f1), System.Math.Abs(f2)))); 46 | } 47 | 48 | private bool AlmostEqual(Point p1, Point p2) { 49 | return AlmostEqual(p1.X, p2.X) && AlmostEqual(p1.Y, p2.Y) && AlmostEqual(p1.Z, p2.Z); 50 | } 51 | 52 | private bool AlmostEqual(AABB aabb1, AABB aabb2) { 53 | return AlmostEqual(aabb1.Min, aabb2.Min) && AlmostEqual(aabb1.Max, aabb2.Max); 54 | } 55 | 56 | public override void Render() { 57 | base.Render(); 58 | DrawOrigin(); 59 | 60 | GL.PushMatrix(); 61 | GL.Scale(3.0f, 3.0f, 3.0f); 62 | obj.DebugRender(); 63 | GL.PopMatrix(); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/OBJPlaneIntersection.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | using CollisionDetectionSelector; 5 | 6 | namespace CollisionDetectionSelector.Samples { 7 | class OBJPlaneIntersection : Application { 8 | OBJLoader loader = null; 9 | OBJ[] objs = new OBJ[] { null, null, null }; 10 | 11 | Plane[] tests = new Plane[] { 12 | new Plane(new Vector3(1f, 1f, 1f), 2.0f), 13 | new Plane(new Vector3(1f, 1f, 1f), 0.0f), 14 | new Plane(new Vector3(-6f, -6f, -6f), -6.0f), 15 | new Plane(new Point(-4f, -8f, -8f), new Point(-5f, -4f, -8f), new Point(-7f, -4f, -8f)) 16 | }; 17 | 18 | public override void Initialize(int width, int height) { 19 | GL.Enable(EnableCap.DepthTest); 20 | GL.Enable(EnableCap.CullFace); 21 | GL.Enable(EnableCap.Lighting); 22 | GL.Enable(EnableCap.Light0); 23 | 24 | GL.Light(LightName.Light0, LightParameter.Position, new float[] { 0.0f, 0.5f, 0.5f, 0.0f }); 25 | GL.Light(LightName.Light0, LightParameter.Ambient, new float[] { 0f, 1f, 0f, 1f }); 26 | GL.Light(LightName.Light0, LightParameter.Diffuse, new float[] { 0f, 1f, 0f, 1f }); 27 | GL.Light(LightName.Light0, LightParameter.Specular, new float[] { 1f, 1f, 1f, 1f }); 28 | 29 | loader = new OBJLoader("Assets/suzanne.obj"); 30 | objs[0] = new OBJ(loader); 31 | objs[1] = new OBJ(loader); 32 | objs[2] = new OBJ(loader); 33 | 34 | objs[1].Position = new Vector3(6.0f, 6.0f, 6.0f); 35 | objs[1].Scale = new Vector3(1.5f, 1.5f, 1.5f); 36 | 37 | objs[2].Position = new Vector3(-6.0f, -6.0f, -6.0f); 38 | objs[1].Scale = new Vector3(1.5f, 1.5f, 1.5f); 39 | objs[2].Rotation = new Vector3(90.0f, 0.0f, 0.0f); 40 | } 41 | 42 | public override void Render() { 43 | GL.Disable(EnableCap.Lighting); 44 | base.Render(); 45 | DrawOrigin(); 46 | GL.Enable(EnableCap.Lighting); 47 | 48 | GL.Color3(0f, 0f, 1f); 49 | foreach (OBJ obj in objs) { 50 | obj.Render(); 51 | } 52 | 53 | GL.Disable(EnableCap.Lighting); 54 | GL.Disable(EnableCap.CullFace); 55 | foreach (Plane test in tests) { 56 | bool intersection = false; 57 | foreach (OBJ obj in objs) { 58 | if (Intersects.OBJPlaneIntersect(test, obj)) { 59 | intersection = true; 60 | } 61 | } 62 | if (intersection) { 63 | GL.Color3(0f, 1f, 0f); 64 | } 65 | else { 66 | GL.Color3(1f, 0f, 0f); 67 | } 68 | test.Render(5f); 69 | } 70 | GL.Enable(EnableCap.CullFace); 71 | GL.Enable(EnableCap.Lighting); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/RaycastSphere.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class RaycastSphere : Application { 7 | public class Touple { 8 | public Ray ray; 9 | public Sphere sphere; 10 | public bool result; 11 | 12 | public Touple(float rayX, float rayY, float rayZ, float normX, float normY, float normZ, 13 | float sphereX, float sphereY, float sphereZ, float rad, bool res) { 14 | ray = new Ray(new Point(rayX, rayY, rayZ), new Vector3(normX, normY, normZ)); 15 | sphere = new Sphere(new Point(sphereX, sphereY, sphereZ), rad); 16 | result = res; 17 | } 18 | } 19 | 20 | Touple[] touples = new Touple[] { 21 | new Touple(-2, 1, 0, 2, 0, 0, 2, 0, 0, 2, true), 22 | new Touple(-2, 0, 0, 2, 0, 0, 2, 2, 0, 2, true), 23 | new Touple(-2, 0, 0, 2, 0, 0, 0, 0, 0, 2, true), 24 | new Touple(-2, 2, 0, 2, -1, 2, 0, 0, 0, 2, true), 25 | new Touple(2, 1, 0, 2, 0, 0, 2, 0, 0, 2, true), 26 | new Touple(-2, 1, 0, -1, 0, 0, 2, 0, 0, 2, false), //causes the error 27 | new Touple(-5, 1, 0, 2, 0.4f, 0, 2, 0, 0, 2, false) 28 | }; 29 | 30 | public override void Initialize(int width, int height) { 31 | GL.Enable(EnableCap.DepthTest); 32 | GL.PointSize(5f); 33 | GL.Enable(EnableCap.CullFace); 34 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 35 | 36 | foreach (Touple touple in touples) { 37 | float t = 0f; 38 | if (LinesAndRays.RaycastSphere(touple.ray, touple.sphere, out t) != touple.result) { 39 | LogError("Expected ray: " + touple.ray + "\nTo " + 40 | (touple.result ? "intersect" : "not intersect") 41 | + " sphere: " + touple.sphere); 42 | } 43 | } 44 | } 45 | 46 | public override void Render() { 47 | //GL.Enable(EnableCap.CullFace); 48 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 49 | 50 | base.Render(); 51 | DrawOrigin(); 52 | 53 | GL.Color3(1f, 0f, 0f); 54 | for (int i = 0; i < 3; ++i) { 55 | touples[i].sphere.Render(); 56 | } 57 | 58 | GL.Color3(0f, 1f, 0f); 59 | foreach (Touple touple in touples) { 60 | touple.ray.Render(); 61 | if (touple.result) { 62 | Point p = new Point(); 63 | LinesAndRays.RaycastSphere(touple.ray, touple.sphere, out p); 64 | GL.Color3(0f, 0f, 1f); 65 | p.Render(); 66 | GL.Color3(0f, 1f, 0f); 67 | } 68 | } 69 | } 70 | 71 | private void Log(string s) { 72 | System.Console.WriteLine(s); 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/OBJTriangleIntersection.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | using CollisionDetectionSelector; 5 | 6 | namespace CollisionDetectionSelector.Samples { 7 | class OBJTriangleIntersection : Application { 8 | OBJLoader loader = null; 9 | OBJ[] objs = new OBJ[] { null, null, null }; 10 | 11 | Triangle[] tests = new Triangle[] { 12 | new Triangle(new Point(-2f, -2f, 0f), new Point(2f, -2f, 0f), new Point(0f, 2f, 0f)), 13 | new Triangle(new Point(-2f, -2f, 4f), new Point(2f, -2f, 4f), new Point(0f, 2f, 4f)), 14 | new Triangle(new Point(-2f, -2f, -4f), new Point(2f, -2f, -4f), new Point(0f, 2f, -4f)), 15 | }; 16 | 17 | public override void Initialize(int width, int height) { 18 | GL.Enable(EnableCap.DepthTest); 19 | GL.Enable(EnableCap.CullFace); 20 | GL.Enable(EnableCap.Lighting); 21 | GL.Enable(EnableCap.Light0); 22 | 23 | GL.Light(LightName.Light0, LightParameter.Position, new float[] { 0.0f, 0.5f, 0.5f, 0.0f }); 24 | GL.Light(LightName.Light0, LightParameter.Ambient, new float[] { 0f, 1f, 0f, 1f }); 25 | GL.Light(LightName.Light0, LightParameter.Diffuse, new float[] { 0f, 1f, 0f, 1f }); 26 | GL.Light(LightName.Light0, LightParameter.Specular, new float[] { 1f, 1f, 1f, 1f }); 27 | 28 | loader = new OBJLoader("Assets/suzanne.obj"); 29 | objs[0] = new OBJ(loader); 30 | objs[1] = new OBJ(loader); 31 | objs[2] = new OBJ(loader); 32 | 33 | objs[1].Position = new Vector3(6.0f, 6.0f, 6.0f); 34 | objs[1].Scale = new Vector3(1.5f, 1.5f, 1.5f); 35 | 36 | objs[2].Position = new Vector3(-6.0f, -6.0f, -6.0f); 37 | objs[1].Scale = new Vector3(1.5f, 1.5f, 1.5f); 38 | objs[2].Rotation = new Vector3(90.0f, 0.0f, 0.0f); 39 | } 40 | 41 | public override void Render() { 42 | GL.Disable(EnableCap.Lighting); 43 | base.Render(); 44 | DrawOrigin(); 45 | GL.Enable(EnableCap.Lighting); 46 | 47 | GL.Color3(0f, 0f, 1f); 48 | foreach (OBJ obj in objs) { 49 | obj.Render(); 50 | } 51 | 52 | GL.Disable(EnableCap.Lighting); 53 | GL.Disable(EnableCap.CullFace); 54 | foreach (Triangle test in tests) { 55 | bool intersection = false; 56 | foreach (OBJ obj in objs) { 57 | if (Intersects.OBJTriangleIntersect(test, obj)) { 58 | intersection = true; 59 | } 60 | } 61 | if (intersection) { 62 | GL.Color3(0f, 1f, 0f); 63 | } 64 | else { 65 | GL.Color3(1f, 0f, 0f); 66 | } 67 | test.Render(); 68 | } 69 | GL.Enable(EnableCap.CullFace); 70 | GL.Enable(EnableCap.Lighting); 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/OBJAABBIntersection.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | using CollisionDetectionSelector; 5 | 6 | namespace CollisionDetectionSelector.Samples { 7 | class OBJAABBIntersection : Application { 8 | OBJLoader loader = null; 9 | OBJ[] objs = new OBJ[] { null , null, null }; 10 | 11 | AABB[] tests = new AABB[] { 12 | new AABB(new Point(2f, 2f, 2f), new Point(6f, 6f, 6f)), 13 | new AABB(new Point(-1f, -1f, -1f), new Point(-7f, -7f, -7f)), 14 | new AABB(new Point(-1f, -1f, -1f), new Point(3f, 3f, 3f)), 15 | new AABB(new Point(1f, 1f, 1f), new Point(3f,3f, 3f)), 16 | }; 17 | 18 | public override void Initialize(int width, int height) { 19 | GL.Enable(EnableCap.DepthTest); 20 | GL.Enable(EnableCap.CullFace); 21 | GL.Enable(EnableCap.Lighting); 22 | GL.Enable(EnableCap.Light0); 23 | 24 | GL.Light(LightName.Light0, LightParameter.Position, new float[] { 0.0f, 0.5f, 0.5f, 0.0f }); 25 | GL.Light(LightName.Light0, LightParameter.Ambient, new float[] { 0f, 1f, 0f, 1f }); 26 | GL.Light(LightName.Light0, LightParameter.Diffuse, new float[] { 0f, 1f, 0f, 1f }); 27 | GL.Light(LightName.Light0, LightParameter.Specular, new float[] { 1f, 1f, 1f, 1f }); 28 | 29 | loader = new OBJLoader("Assets/suzanne.obj"); 30 | objs[0] = new OBJ(loader); 31 | objs[1] = new OBJ(loader); 32 | objs[2] = new OBJ(loader); 33 | 34 | objs[1].Position = new Vector3(6.0f, 6.0f, 6.0f); 35 | objs[1].Scale = new Vector3(1.5f, 1.5f, 1.5f); 36 | 37 | objs[2].Position = new Vector3(-6.0f, -6.0f, -6.0f); 38 | objs[1].Scale = new Vector3(1.5f, 1.5f, 1.5f); 39 | objs[2].Rotation = new Vector3(90.0f, 0.0f, 0.0f); 40 | } 41 | 42 | public override void Render() { 43 | GL.Disable(EnableCap.Lighting); 44 | base.Render(); 45 | DrawOrigin(); 46 | GL.Enable(EnableCap.Lighting); 47 | 48 | GL.Color3(0f, 0f, 1f); 49 | foreach (OBJ obj in objs) { 50 | obj.Render(); 51 | } 52 | 53 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 54 | GL.Disable(EnableCap.Lighting); 55 | foreach (AABB test in tests) { 56 | bool intersection = false; 57 | foreach (OBJ obj in objs) { 58 | if (Intersects.OBJAABBIntersect(test, obj)) { 59 | intersection = true; 60 | } 61 | } 62 | if (intersection) { 63 | GL.Color3(0f, 1f, 0f); 64 | } 65 | else { 66 | GL.Color3(1f, 0f, 0f); 67 | } 68 | test.Render(); 69 | } 70 | GL.Enable(EnableCap.Lighting); 71 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Primitive/Plane.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using OpenTK.Graphics.OpenGL; 3 | using Math_Implementation; 4 | 5 | namespace CollisionDetectionSelector.Primitive { 6 | class Plane { 7 | protected Vector3 _normal = new Vector3(); 8 | 9 | public Vector3 Normal { 10 | get { 11 | return _normal; 12 | } 13 | //normalized when set 14 | set { 15 | _normal = Vector3.Normalize(value); 16 | } 17 | } 18 | public float Distance = 0f; 19 | 20 | public Plane() { 21 | //default plane 22 | //0,0,1 distance is 0 23 | Normal = new Vector3(0, 0, 1); 24 | Distance = 0f; 25 | } 26 | public Plane(Vector3 norm,float dist) { 27 | Normal = norm; 28 | Distance = dist; 29 | } 30 | public Plane(Point a, Point b, Point c) { 31 | Vector3 ab = new Vector3(b.X - a.X, b.Y - a.Y, b.Z - a.Z); 32 | Vector3 ac = new Vector3(c.X - a.X, c.Y - a.Y, c.Z - a.Z); 33 | //construct plane from point 34 | Normal = Vector3.Normalize(Vector3.Cross(ab, ac)); 35 | Distance = Vector3.Dot(Normal, new Vector3(a.X,a.Y,a.Z)); 36 | } 37 | // No need to edit anything below this 38 | public void Render(float scale = 1f) { 39 | //Debug Normal 40 | /* // GL.Color3(1f, 1f, 0f); 41 | GL.Begin(PrimitiveType.Lines); 42 | GL.Vertex3(0f, 0f, 0f); 43 | GL.Vertex3(Normal.X * 500, Normal.Y * 500, Normal.Z * 500); 44 | GL.End(); */ 45 | 46 | // Construct plane orientation 47 | Vector3 forward = new Vector3(Normal.X, Normal.Y, Normal.Z); 48 | Vector3 up = new Vector3(0f, 1f, 0f); 49 | Vector3 right = Vector3.Cross(forward, up); 50 | up = Vector3.Cross(right, forward); 51 | 52 | // Because this is going to be a matrix, it needs to be normalized 53 | forward.Normalize(); 54 | right.Normalize(); 55 | up.Normalize(); 56 | 57 | // Create plane model matrix 58 | Matrix4 rot = new Matrix4(right.X, up.X, -forward.X, 0.0f, 59 | right.Y, up.Y, -forward.Y, 0.0f, 60 | right.Z, up.Z, -forward.Z, 0.0f, 61 | 0.0f, 0.0f, 0.0f, 1.0f); 62 | Matrix4 trans = Matrix4.Translate(Normal * Distance); 63 | Matrix4 model = trans * rot; 64 | 65 | // Load matrix and render plane 66 | GL.PushMatrix(); 67 | GL.MultMatrix(model.OpenGL); 68 | GL.Scale(scale, scale, scale); 69 | //GL.Color3(1f, 1f, 1f); 70 | GL.Begin(PrimitiveType.Quads); 71 | GL.Vertex3(-1, -1, 0); 72 | GL.Vertex3(-1, 1, 0); 73 | GL.Vertex3(1, 1, 0); 74 | GL.Vertex3(1, -1, 0); 75 | GL.End(); 76 | GL.PopMatrix(); 77 | } 78 | 79 | public override string ToString() { 80 | return "N: (" + Normal.X + ", " + Normal.Y + ", " + Normal.Z + "), D: " + Distance; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/PointInTriangleSample.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class PointInTriangle : Application { 7 | protected Point[] points = null; 8 | 9 | Triangle triangle = new Triangle(new Point(-1.0f, 1.0f, 1.0f), new Point(0.0f, -1.0f, 1.0f), new Point(1.0f, 1.0f, 1.0f)); 10 | 11 | public override void Initialize(int width, int height) { 12 | GL.Enable(EnableCap.DepthTest); 13 | GL.PointSize(4f); 14 | GL.Disable(EnableCap.CullFace); 15 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 16 | 17 | int i_min = -2; 18 | int i_max = 3; 19 | int j_min = -2; 20 | int j_max = 3; 21 | int k_min = -1; 22 | int k_max = 3; 23 | 24 | int indexer = 0; 25 | for (int i = i_min; i < i_max; ++i) { 26 | for (int j = j_min; j < j_max; ++j) { 27 | for (int k = k_min; k < k_max; ++k) { 28 | indexer++; 29 | } 30 | } 31 | } 32 | 33 | points = new Point[indexer + 3]; 34 | indexer = 0; 35 | 36 | for (int i = i_min; i < i_max; ++i) { 37 | for (int j = j_min; j < j_max; ++j) { 38 | for (int k = k_min; k < k_max; ++k) { 39 | points[indexer++] = new Point(i, j, k); 40 | } 41 | } 42 | } 43 | 44 | points[indexer++] = new Point(0.5f, 0.5f, 1f); 45 | points[indexer++] = new Point(0.5f, -0.25f, 1f); 46 | points[indexer++] = new Point(-0.25f, -0.25f, 1f); 47 | 48 | 49 | int[] colliding = new int[] { 34, 46, 50, 54, 74, 100, 102 }; 50 | int col_index = 0; 51 | 52 | for (int i = 0; i < points.Length; ++i) { 53 | if (col_index < colliding.Length && i == colliding[col_index]) { 54 | if (!Collisions.PointInTriangle(triangle, points[i])) { 55 | LogError("point " + i + " SHOULD be colliding!"); 56 | } 57 | 58 | col_index++; 59 | } 60 | else { 61 | if (Collisions.PointInTriangle(triangle, points[i])) { 62 | LogError("point " + i + " should NOT be colliding!"); 63 | } 64 | } 65 | } 66 | } 67 | 68 | public override void Render() { 69 | base.Render(); 70 | DrawOrigin(); 71 | 72 | GL.Color3(0.0f, 0.0f, 1.0f); 73 | triangle.Render(); 74 | 75 | foreach (Point point in points) { 76 | if (Collisions.PointInTriangle(triangle, point)) { 77 | GL.Color3(0.0f, 1.0f, 0.0f); 78 | } 79 | else { 80 | GL.Color3(1.0f, 0.0f, 0.0f); 81 | } 82 | 83 | point.Render(); 84 | } 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/ClosesPointOnPlane.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class ClosestPointPlaneSample : Application { 7 | protected Vector3 cameraAngle = new Vector3(120.0f, -10f, 20.0f); 8 | protected float rads = (float)(System.Math.PI / 180.0f); 9 | 10 | Plane plane = new Plane(new Point(5, 6, 7), new Point(6, 5, 4), new Point(1, 2, 3)); 11 | 12 | Point point = new Point(2f, 5f, -3f); 13 | 14 | public override void Initialize(int width, int height) { 15 | GL.PointSize(2f); 16 | } 17 | 18 | public override void Render() { 19 | Vector3 eyePos = new Vector3(); 20 | eyePos.X = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 21 | eyePos.Y = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.Y * rads); 22 | eyePos.Z = -cameraAngle.Z * (float)System.Math.Cos(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 23 | 24 | Matrix4 lookAt = Matrix4.LookAt(eyePos, new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f)); 25 | GL.LoadMatrix(Matrix4.Transpose(lookAt).Matrix); 26 | 27 | DrawOrigin(); 28 | 29 | GL.Color3(1f, 1f, 1f); 30 | plane.Render(4f); 31 | 32 | Point closest = Collisions.ClosestPoint(plane, point); 33 | float distance = Collisions.DistanceFromPlane(point, plane); 34 | Vector3 vec = point.ToVector() - plane.Normal * distance; 35 | 36 | GL.Color3(0f, 0f, 1f); 37 | GL.Begin(PrimitiveType.Lines); 38 | GL.Vertex3(point.X, point.Y, point.Z); 39 | GL.Vertex3(vec.X, vec.Y, vec.Z); 40 | GL.End(); 41 | 42 | GL.Color3(1f, 0f, 1f); 43 | GL.Begin(PrimitiveType.Lines); 44 | GL.Vertex3(closest.X, closest.Y, closest.Z); 45 | GL.Vertex3(closest.X + plane.Normal.Z, closest.Y + plane.Normal.Y, closest.Z + plane.Normal.Z); 46 | GL.End(); 47 | 48 | GL.Color3(1f, 0f, 0f); 49 | point.Render(); 50 | 51 | GL.Color3(0, 1f, 0f); 52 | closest.Render(); 53 | } 54 | 55 | public override void Update(float deltaTime) { 56 | cameraAngle.X += 45.0f * deltaTime; 57 | } 58 | 59 | protected void DrawOrigin() { 60 | GL.Begin(PrimitiveType.Lines); 61 | GL.Color3(1f, 0f, 0f); 62 | GL.Vertex3(0f, 0f, 0f); 63 | GL.Vertex3(1f, 0f, 0f); 64 | GL.Color3(0f, 1f, 0f); 65 | GL.Vertex3(0f, 0f, 0f); 66 | GL.Vertex3(0f, 1f, 0f); 67 | GL.Color3(0f, 0f, 1f); 68 | GL.Vertex3(0f, 0f, 0f); 69 | GL.Vertex3(0f, 0f, 1f); 70 | GL.End(); 71 | } 72 | 73 | public override void Resize(int width, int height) { 74 | GL.Viewport(0, 0, width, height); 75 | GL.MatrixMode(MatrixMode.Projection); 76 | float aspect = (float)width / (float)height; 77 | Matrix4 perspective = Matrix4.Perspective(60, aspect, 0.01f, 1000.0f); 78 | GL.LoadMatrix(Matrix4.Transpose(perspective).Matrix); 79 | GL.MatrixMode(MatrixMode.Modelview); 80 | GL.LoadIdentity(); 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/PlaneSample.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class PlaneSample : Application { 7 | protected Vector3 cameraAngle = new Vector3(120.0f, -10f, 20.0f); 8 | protected float rads = (float)(System.Math.PI / 180.0f); 9 | 10 | Plane[] plane = new Plane[] { 11 | new Plane(), 12 | new Plane(), 13 | new Plane(new Vector3(0f, 5f, 3f), 4f), 14 | new Plane(new Point(5, 6, 7), new Point(6, 5, 4), new Point(1, 2, 3)), 15 | new Plane(new Point(0, 0, 2), new Point(1, 1, 2), new Point(2, 0, 2)) 16 | }; 17 | 18 | public override void Initialize(int width, int height) { 19 | //GL.Enable(EnableCap.CullFace); 20 | GL.Enable(EnableCap.DepthTest); 21 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); 22 | GL.PointSize(2f); 23 | 24 | plane[1].Normal = new Vector3(1f, 1f, 0f); 25 | plane[1].Distance = 3.0f; 26 | plane[3].Distance = 4f; 27 | 28 | } 29 | 30 | public override void Render() { 31 | Vector3 eyePos = new Vector3(); 32 | eyePos.X = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 33 | eyePos.Y = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.Y * rads); 34 | eyePos.Z = -cameraAngle.Z * (float)System.Math.Cos(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 35 | 36 | Matrix4 lookAt = Matrix4.LookAt(eyePos, new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f)); 37 | GL.LoadMatrix(Matrix4.Transpose(lookAt).Matrix); 38 | 39 | DrawOrigin(); 40 | 41 | float[][] renderColors = new float[][] { 42 | new float[] { 1f, 1f, 0f }, 43 | new float[] { 1f, 0f, 1f }, 44 | new float[] { 0f, 1f, 1f }, 45 | new float[] { 1f, 0f, 0f }, 46 | new float[] { 0f, 1f, 0f } 47 | }; 48 | 49 | for (int i = 0; i < plane.Length; ++i) { 50 | GL.Color3(renderColors[i][0], renderColors[i][1], renderColors[i][2]); 51 | plane[i].Render(); 52 | } 53 | } 54 | 55 | public override void Update(float deltaTime) { 56 | cameraAngle.X += 45.0f * deltaTime; 57 | } 58 | 59 | protected void DrawOrigin() { 60 | GL.Begin(PrimitiveType.Lines); 61 | GL.Color3(1f, 0f, 0f); 62 | GL.Vertex3(0f, 0f, 0f); 63 | GL.Vertex3(1f, 0f, 0f); 64 | GL.Color3(0f, 1f, 0f); 65 | GL.Vertex3(0f, 0f, 0f); 66 | GL.Vertex3(0f, 1f, 0f); 67 | GL.Color3(0f, 0f, 1f); 68 | GL.Vertex3(0f, 0f, 0f); 69 | GL.Vertex3(0f, 0f, 1f); 70 | GL.End(); 71 | } 72 | 73 | public override void Resize(int width, int height) { 74 | GL.Viewport(0, 0, width, height); 75 | GL.MatrixMode(MatrixMode.Projection); 76 | float aspect = (float)width / (float)height; 77 | Matrix4 perspective = Matrix4.Perspective(60, aspect, 0.01f, 1000.0f); 78 | GL.LoadMatrix(Matrix4.Transpose(perspective).Matrix); 79 | GL.MatrixMode(MatrixMode.Modelview); 80 | GL.LoadIdentity(); 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/PointOnLineSample.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class PointOnLineSample : Application { 7 | protected Vector3 cameraAngle = new Vector3(120.0f, -10f, 20.0f); 8 | protected float rads = (float)(System.Math.PI / 180.0f); 9 | 10 | Line testLine = new Line(new Point(-3, -2, -1), new Point(3, 2, 1)); 11 | Point[] testPoints = new Point[] { 12 | new Point(0, 0, 0), 13 | new Point(-3, -2, -1), 14 | new Point(3, 2, 1), 15 | new Point(7, -2, -1), 16 | new Point(-4, -7, -8), 17 | new Point(7, 8, 5), 18 | new Point(1, 5, -5), 19 | new Point(-6, 5, 7), 20 | new Point(1, 6, 8), 21 | new Point(-7, -10, -4), 22 | new Point(5, 5, 3) 23 | }; 24 | 25 | public override void Initialize(int width, int height) { 26 | GL.Enable(EnableCap.DepthTest); 27 | GL.PointSize(4f); 28 | 29 | for (int i = 0; i < 3; ++i) { 30 | if (!Collisions.PointOnLine(testPoints[i], testLine)) { 31 | System.Console.ForegroundColor = System.ConsoleColor.Red; 32 | System.Console.WriteLine("Expected point: " + testPoints[i].ToString() + " to be on Line!"); 33 | } 34 | } 35 | 36 | for (int i = 3; i < testPoints.Length; ++i) { 37 | if (Collisions.PointOnLine(testPoints[i], testLine)) { 38 | System.Console.ForegroundColor = System.ConsoleColor.Red; 39 | System.Console.WriteLine("Expected point: " + testPoints[i].ToString() + " to be on Line!"); 40 | } 41 | } 42 | } 43 | 44 | public override void Render() { 45 | Vector3 eyePos = new Vector3(); 46 | eyePos.X = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 47 | eyePos.Y = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.Y * rads); 48 | eyePos.Z = -cameraAngle.Z * (float)System.Math.Cos(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 49 | 50 | Matrix4 lookAt = Matrix4.LookAt(eyePos, new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f)); 51 | GL.LoadMatrix(Matrix4.Transpose(lookAt).Matrix); 52 | 53 | GL.Color3(1f, 0f, 1f); 54 | testLine.Render(); 55 | 56 | foreach (Point point in testPoints) { 57 | if (Collisions.PointOnLine(point, testLine)) { 58 | GL.Color3(1f, 0f, 0f); 59 | } 60 | else { 61 | GL.Color3(0f, 0f, 1f); 62 | } 63 | point.Render(); 64 | } 65 | } 66 | 67 | public override void Update(float deltaTime) { 68 | cameraAngle.X += 45.0f * deltaTime; 69 | } 70 | 71 | public override void Resize(int width, int height) { 72 | GL.Viewport(0, 0, width, height); 73 | GL.MatrixMode(MatrixMode.Projection); 74 | float aspect = (float)width / (float)height; 75 | Matrix4 perspective = Matrix4.Perspective(60, aspect, 0.01f, 1000.0f); 76 | GL.LoadMatrix(Matrix4.Transpose(perspective).Matrix); 77 | GL.MatrixMode(MatrixMode.Modelview); 78 | GL.LoadIdentity(); 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/ClosestPointOnLineSample.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class ClosestPointLine : Application { 7 | protected Vector3 cameraAngle = new Vector3(120.0f, -10f, 20.0f); 8 | protected float rads = (float)(System.Math.PI / 180.0f); 9 | 10 | Line testLine = new Line(new Point(-3, -2, -1), new Point(1, 2, 3)); 11 | Point[] testPoints = new Point[] { 12 | new Point(7, -2, -1), 13 | new Point(-4, -7, -8), 14 | new Point(7, 8, 5), 15 | new Point(1, 5, -5), 16 | new Point(-6, 5, 7), 17 | new Point(1, 6, 8), 18 | new Point(-7, -10, -4), 19 | new Point(5, 5, 3) 20 | }; 21 | 22 | public override void Initialize(int width, int height) { 23 | GL.Enable(EnableCap.DepthTest); 24 | GL.PointSize(4f); 25 | } 26 | 27 | public override void Render() { 28 | Vector3 eyePos = new Vector3(); 29 | eyePos.X = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 30 | eyePos.Y = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.Y * rads); 31 | eyePos.Z = -cameraAngle.Z * (float)System.Math.Cos(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 32 | 33 | Matrix4 lookAt = Matrix4.LookAt(eyePos, new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f)); 34 | GL.LoadMatrix(Matrix4.Transpose(lookAt).Matrix); 35 | 36 | DrawOrigin(); 37 | 38 | GL.Color3(1f, 0f, 1f); 39 | testLine.Render(); 40 | 41 | GL.Color3(0f, 1f, 1f); 42 | foreach (Point point in testPoints) { 43 | point.Render(); 44 | } 45 | 46 | GL.Color3(1f, 1f, 0f); 47 | foreach (Point point in testPoints) { 48 | Point closest = Collisions.ClosestPoint(testLine, point); 49 | closest.Render(); 50 | } 51 | 52 | GL.Color3(1f, 1f, 1f); 53 | foreach (Point point in testPoints) { 54 | Point closest = Collisions.ClosestPoint(testLine, point); 55 | Line newLine = new Line(closest, point); 56 | newLine.Render(); 57 | } 58 | } 59 | 60 | public override void Update(float deltaTime) { 61 | cameraAngle.X += 45.0f * deltaTime; 62 | } 63 | 64 | protected void DrawOrigin() { 65 | GL.Begin(PrimitiveType.Lines); 66 | GL.Color3(1f, 0f, 0f); 67 | GL.Vertex3(0f, 0f, 0f); 68 | GL.Vertex3(1f, 0f, 0f); 69 | GL.Color3(0f, 1f, 0f); 70 | GL.Vertex3(0f, 0f, 0f); 71 | GL.Vertex3(0f, 1f, 0f); 72 | GL.Color3(0f, 0f, 1f); 73 | GL.Vertex3(0f, 0f, 0f); 74 | GL.Vertex3(0f, 0f, 1f); 75 | GL.End(); 76 | } 77 | 78 | public override void Resize(int width, int height) { 79 | GL.Viewport(0, 0, width, height); 80 | GL.MatrixMode(MatrixMode.Projection); 81 | float aspect = (float)width / (float)height; 82 | Matrix4 perspective = Matrix4.Perspective(60, aspect, 0.01f, 1000.0f); 83 | GL.LoadMatrix(Matrix4.Transpose(perspective).Matrix); 84 | GL.MatrixMode(MatrixMode.Modelview); 85 | GL.LoadIdentity(); 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/LineSample.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class LineSample : Application { 7 | protected Vector3 cameraAngle = new Vector3(120.0f, -10f, 20.0f); 8 | protected float rads = (float)(System.Math.PI / 180.0f); 9 | 10 | Line[] origin = new Line[] { 11 | new Line(new Point(0, 0, 0), new Point(1, 0, 0)), 12 | new Line(new Point(0, 0, 0), new Point(0, 1, 0)), 13 | new Line(new Point(0, 0, 0), new Point(0, 0, 1)) 14 | }; 15 | 16 | Line[] random = new Line[] { 17 | new Line(new Point(-7, 5, -3), new Point(8, 5, -10)), 18 | new Line(new Point(-8, -8, 6), new Point(-9, -2, -10)), 19 | new Line(new Point(-4, -6, -3), new Point(-9, -1, 5)), 20 | new Line(new Point(-6, 0, 2), new Point(-1, 1, 3)) 21 | }; 22 | 23 | float[][] colors = new float[][] { 24 | new float[] { 1f, 0f, 1f }, 25 | new float[] { 0f, 1f, 1f }, 26 | new float[] { 1f, 1f, 0f }, 27 | new float[] { 1f, 1f, 1f }, 28 | }; 29 | 30 | public override void Initialize(int width, int height) { 31 | GL.Enable(EnableCap.DepthTest); 32 | 33 | /*System.Random r = new System.Random(); 34 | string output = "new Line(new Point(" + (r.Next() % 20 - 10) + ", " + (r.Next() % 20 - 10) + ", " + (r.Next() % 20 - 10) + "), new Point(" + (r.Next() % 20 - 10) + ", " + (r.Next() % 20 - 10) + ", " + (r.Next() % 20 - 10) + ")),\n"; 35 | for (int i = 0; i < 3; ++i) { 36 | output += "new Line(new Point(" + (r.Next() % 20 - 10) + ", " + (r.Next() % 20 - 10) + ", " + (r.Next() % 20 - 10) + "), new Point(" + (r.Next() % 20 - 10) + ", " + (r.Next() % 20 - 10) + ", " + (r.Next() % 20 - 10) + ")),\n"; 37 | } 38 | System.IO.File.WriteAllText(@"C:\Users\WinVPC\Desktop\Lines.txt", output);*/ 39 | } 40 | 41 | public override void Render() { 42 | Vector3 eyePos = new Vector3(); 43 | eyePos.X = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 44 | eyePos.Y = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.Y * rads); 45 | eyePos.Z = -cameraAngle.Z * (float)System.Math.Cos(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 46 | 47 | Matrix4 lookAt = Matrix4.LookAt(eyePos, new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f)); 48 | GL.LoadMatrix(Matrix4.Transpose(lookAt).Matrix); 49 | 50 | GL.Color3(1f, 0f, 0f); 51 | origin[0].Render(); 52 | GL.Color3(0f, 1f, 0f); 53 | origin[1].Render(); 54 | GL.Color3(0f, 0f, 1f); 55 | origin[2].Render(); 56 | 57 | for (int i = 0; i < random.Length; ++i) { 58 | GL.Color3(colors[i][0], colors[i][1], colors[i][2]); 59 | random[i].Render(); 60 | } 61 | } 62 | 63 | public override void Update(float deltaTime) { 64 | cameraAngle.X += 45.0f * deltaTime; 65 | } 66 | 67 | public override void Resize(int width, int height) { 68 | GL.Viewport(0, 0, width, height); 69 | GL.MatrixMode(MatrixMode.Projection); 70 | float aspect = (float)width / (float)height; 71 | Matrix4 perspective = Matrix4.Perspective(60, aspect, 0.01f, 1000.0f); 72 | GL.LoadMatrix(Matrix4.Transpose(perspective).Matrix); 73 | GL.MatrixMode(MatrixMode.Modelview); 74 | GL.LoadIdentity(); 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/PointOnRay.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class PointOnray : Application { 7 | protected Vector3 cameraAngle = new Vector3(120.0f, -10f, 20.0f); 8 | protected float rads = (float)(System.Math.PI / 180.0f); 9 | 10 | Ray testRay = new Ray(new Point(-3, -2, -1), new Vector3(3, 2, 1)); 11 | Point[] testPoints = new Point[] { 12 | new Point(-3, -2, -1), 13 | new Point(12, 8, 4), 14 | new Point(0, 0, 0), 15 | new Point(-18, -12, -6), 16 | new Point(-4, -7, -8), 17 | new Point(7, 8, 5), 18 | new Point(1, 5, -5), 19 | new Point(-6, 5, 7), 20 | new Point(1, 6, 8), 21 | new Point(-7, -10, -4), 22 | new Point(-4.5f, -3f, -1.5f) 23 | }; 24 | 25 | public override void Initialize(int width, int height) { 26 | GL.Enable(EnableCap.DepthTest); 27 | GL.PointSize(4f); 28 | 29 | Point p1 = new Point(0, 0, 0); 30 | Point p2 = new Point(0, 0, 0); 31 | LogError("Points equal: " + (p1.X == p2.X && p1.Y == p2.Y && p1.Z == p2.Z)); 32 | LogError("Points equal: " + (p1 == p2)); 33 | 34 | for (int i = 0; i < 3; ++i) { 35 | if (!Collisions.PointOnRay(testPoints[i], testRay)) { 36 | System.Console.ForegroundColor = System.ConsoleColor.Red; 37 | System.Console.WriteLine("Expected point: " + testPoints[i].ToString() + " to be on Ray!"); 38 | } 39 | } 40 | 41 | for (int i = 3; i < testPoints.Length; ++i) { 42 | if (Collisions.PointOnRay(testPoints[i], testRay)) { 43 | System.Console.ForegroundColor = System.ConsoleColor.Red; 44 | System.Console.WriteLine("Expected point: " + testPoints[i].ToString() + " to NOT be on Ray!"); 45 | } 46 | } 47 | } 48 | 49 | public override void Render() { 50 | Vector3 eyePos = new Vector3(); 51 | eyePos.X = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 52 | eyePos.Y = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.Y * rads); 53 | eyePos.Z = -cameraAngle.Z * (float)System.Math.Cos(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 54 | 55 | Matrix4 lookAt = Matrix4.LookAt(eyePos, new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f)); 56 | GL.LoadMatrix(Matrix4.Transpose(lookAt).Matrix); 57 | 58 | GL.Color3(1f, 0f, 1f); 59 | testRay.Render(); 60 | 61 | foreach (Point point in testPoints) { 62 | if (Collisions.PointOnRay(point, testRay)) { 63 | GL.Color3(1f, 0f, 0f); 64 | } 65 | else { 66 | GL.Color3(0f, 0f, 1f); 67 | } 68 | point.Render(); 69 | } 70 | } 71 | 72 | public override void Update(float deltaTime) { 73 | cameraAngle.X += 45.0f * deltaTime; 74 | } 75 | 76 | public override void Resize(int width, int height) { 77 | GL.Viewport(0, 0, width, height); 78 | GL.MatrixMode(MatrixMode.Projection); 79 | float aspect = (float)width / (float)height; 80 | Matrix4 perspective = Matrix4.Perspective(60, aspect, 0.01f, 1000.0f); 81 | GL.LoadMatrix(Matrix4.Transpose(perspective).Matrix); 82 | GL.MatrixMode(MatrixMode.Modelview); 83 | GL.LoadIdentity(); 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/RaySample.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class RaySample : Application { 7 | protected Vector3 cameraAngle = new Vector3(120.0f, -10f, 20.0f); 8 | protected float rads = (float)(System.Math.PI / 180.0f); 9 | 10 | Line[] origin = new Line[] { 11 | new Line(new Point(0, 0, 0), new Point(1, 0, 0)), 12 | new Line(new Point(0, 0, 0), new Point(0, 1, 0)), 13 | new Line(new Point(0, 0, 0), new Point(0, 0, 1)) 14 | }; 15 | 16 | Ray[] random = new Ray[] { 17 | new Ray(), 18 | new Ray(new Point(8, 2, -7), new Vector3(1, 7, -3)), 19 | new Ray(new Point(-2, 3, 2), new Vector3(-4, -5, 3)), 20 | new Ray(new Vector3(-3, 2, 3), new Vector3(0, 5, 1)), 21 | new Ray(new Vector3(7, -1, -4), new Vector3(-9, 5, -8)), 22 | }; 23 | 24 | float[][] colors = new float[][] { 25 | new float[] { 1f, 0f, 1f }, 26 | new float[] { 0f, 1f, 1f }, 27 | new float[] { 1f, 1f, 0f }, 28 | new float[] { 1f, 1f, 1f }, 29 | new float[] { 0.5f, 0.7f, 0.2f }, 30 | }; 31 | 32 | public override void Initialize(int width, int height) { 33 | GL.Enable(EnableCap.DepthTest); 34 | 35 | /*System.Random r = new System.Random(); 36 | string output = "new Ray(new Point(" + (r.Next() % 20 - 10) + ", " + (r.Next() % 20 - 10) + ", " + (r.Next() % 20 - 10) + "), new Vector3(" + (r.Next() % 20 - 10) + ", " + (r.Next() % 20 - 10) + ", " + (r.Next() % 20 - 10) + ")),\n"; 37 | for (int i = 0; i < 3; ++i) { 38 | output += "new Ray(new Point(" + (r.Next() % 20 - 10) + ", " + (r.Next() % 20 - 10) + ", " + (r.Next() % 20 - 10) + "), new Vector3(" + (r.Next() % 20 - 10) + ", " + (r.Next() % 20 - 10) + ", " + (r.Next() % 20 - 10) + ")),\n"; 39 | } 40 | System.IO.File.WriteAllText(@"C:\Users\WinVPC\Desktop\Rays.txt", output);*/ 41 | } 42 | 43 | public override void Render() { 44 | Vector3 eyePos = new Vector3(); 45 | eyePos.X = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 46 | eyePos.Y = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.Y * rads); 47 | eyePos.Z = -cameraAngle.Z * (float)System.Math.Cos(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 48 | 49 | Matrix4 lookAt = Matrix4.LookAt(eyePos, new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f)); 50 | GL.LoadMatrix(Matrix4.Transpose(lookAt).Matrix); 51 | 52 | GL.Color3(1f, 0f, 0f); 53 | origin[0].Render(); 54 | GL.Color3(0f, 1f, 0f); 55 | origin[1].Render(); 56 | GL.Color3(0f, 0f, 1f); 57 | origin[2].Render(); 58 | 59 | for (int i = 0; i < random.Length; ++i) { 60 | GL.Color3(colors[i][0], colors[i][1], colors[i][2]); 61 | random[i].Render(); 62 | } 63 | } 64 | 65 | public override void Update(float deltaTime) { 66 | cameraAngle.X += 45.0f * deltaTime; 67 | } 68 | 69 | public override void Resize(int width, int height) { 70 | GL.Viewport(0, 0, width, height); 71 | GL.MatrixMode(MatrixMode.Projection); 72 | float aspect = (float)width / (float)height; 73 | Matrix4 perspective = Matrix4.Perspective(60, aspect, 0.01f, 1000.0f); 74 | GL.LoadMatrix(Matrix4.Transpose(perspective).Matrix); 75 | GL.MatrixMode(MatrixMode.Modelview); 76 | GL.LoadIdentity(); 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/ClosestPointOnRay.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class ClosestRayLine : Application { 7 | protected Vector3 cameraAngle = new Vector3(120.0f, -10f, 20.0f); 8 | protected float rads = (float)(System.Math.PI / 180.0f); 9 | 10 | Ray testRay = new Ray(new Point(-10, -8, 1), new Vector3(1, 2, 3)); 11 | Point[] testPoints = new Point[] { 12 | new Point(-8, -5, -8), 13 | new Point(-6, -9, 8), 14 | new Point(-9, -5, 5), 15 | new Point(-4, 3, -3), 16 | new Point(2, 1, -10), 17 | new Point(8, 5, 2), 18 | new Point(4, -3, -8) 19 | }; 20 | 21 | public override void Initialize(int width, int height) { 22 | GL.Enable(EnableCap.DepthTest); 23 | GL.PointSize(4f); 24 | 25 | /*System.Random r = new System.Random(); 26 | string output = "new Point(" + (r.Next() % 20 - 10) + ", " + (r.Next() % 20 - 10) + ", " + (r.Next() % 20 - 10) + "),\n"; 27 | for (int i = 0; i < 6; ++i) { 28 | output += "new Point(" + (r.Next() % 20 - 10) + ", " + (r.Next() % 20 - 10) + ", " + (r.Next() % 20 - 10) + "),\n"; 29 | } 30 | System.IO.File.WriteAllText(@"C:\Users\WinVPC\Desktop\Points.txt", output);*/ 31 | 32 | } 33 | 34 | public override void Render() { 35 | Vector3 eyePos = new Vector3(); 36 | eyePos.X = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 37 | eyePos.Y = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.Y * rads); 38 | eyePos.Z = -cameraAngle.Z * (float)System.Math.Cos(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 39 | 40 | Matrix4 lookAt = Matrix4.LookAt(eyePos, new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f)); 41 | GL.LoadMatrix(Matrix4.Transpose(lookAt).Matrix); 42 | 43 | DrawOrigin(); 44 | 45 | GL.Color3(1f, 0f, 1f); 46 | testRay.Render(); 47 | 48 | GL.Color3(0f, 1f, 1f); 49 | foreach (Point point in testPoints) { 50 | point.Render(); 51 | } 52 | 53 | GL.Color3(1f, 1f, 0f); 54 | foreach (Point point in testPoints) { 55 | Point closest = Collisions.ClosestPoint(testRay, point); 56 | closest.Render(); 57 | } 58 | 59 | GL.Color3(1f, 1f, 1f); 60 | foreach (Point point in testPoints) { 61 | Point closest = Collisions.ClosestPoint(testRay, point); 62 | Line newLine = new Line(closest, point); 63 | newLine.Render(); 64 | } 65 | } 66 | 67 | public override void Update(float deltaTime) { 68 | cameraAngle.X += 45.0f * deltaTime; 69 | } 70 | 71 | protected void DrawOrigin() { 72 | GL.Begin(PrimitiveType.Lines); 73 | GL.Color3(1f, 0f, 0f); 74 | GL.Vertex3(0f, 0f, 0f); 75 | GL.Vertex3(1f, 0f, 0f); 76 | GL.Color3(0f, 1f, 0f); 77 | GL.Vertex3(0f, 0f, 0f); 78 | GL.Vertex3(0f, 1f, 0f); 79 | GL.Color3(0f, 0f, 1f); 80 | GL.Vertex3(0f, 0f, 0f); 81 | GL.Vertex3(0f, 0f, 1f); 82 | GL.End(); 83 | } 84 | 85 | public override void Resize(int width, int height) { 86 | GL.Viewport(0, 0, width, height); 87 | GL.MatrixMode(MatrixMode.Projection); 88 | float aspect = (float)width / (float)height; 89 | Matrix4 perspective = Matrix4.Perspective(60, aspect, 0.01f, 1000.0f); 90 | GL.LoadMatrix(Matrix4.Transpose(perspective).Matrix); 91 | GL.MatrixMode(MatrixMode.Modelview); 92 | GL.LoadIdentity(); 93 | } 94 | } 95 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Primitive/AABB.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using OpenTK.Graphics.OpenGL; 3 | using Math_Implementation; 4 | 5 | namespace CollisionDetectionSelector.Primitive { 6 | class AABB { 7 | public Point Min = new Point(); 8 | public Point Max = new Point(); 9 | 10 | public Point Center { 11 | get { 12 | return new Point(Min.X+(Max.X - Min.X) / 2f, Min.Y+(Max.Y - Min.Y) / 2f, Min.Z+(Max.Z - Min.Z) / 2f); 13 | } 14 | } 15 | public Vector3 Extents { 16 | get { 17 | return new Vector3((Max.X - Center.X), (Max.Y - Center.Y), (Max.Z - Center.Z)); 18 | } 19 | } 20 | public bool IsValid { 21 | get { 22 | return (Min.X < Max.X && Min.Y < Max.Y && Min.Z < Max.Z); 23 | } 24 | } 25 | public void Fix() { 26 | //store old Min 27 | Point _max = new Point(Max); 28 | //change new "Min" to previous max 29 | if (Min.X > Max.X) { 30 | Max.X = Min.X; 31 | Min.X = _max.X; 32 | } 33 | if (Min.Y > Max.Y) { 34 | Max.Y = Min.Y; 35 | Min.Y = _max.Y; 36 | } 37 | if (Min.Z > Max.Z) { 38 | Max.Z = Min.Z; 39 | Min.Z = _max.Z; 40 | } 41 | } 42 | public AABB() { 43 | //make unit AABB 44 | //min=-1, max=+1 on all axiis 45 | Min = new Point(-1, -1, -1); 46 | Max = new Point(1, 1, 1); 47 | } 48 | public AABB(Point min, Point max) { 49 | //set min/max 50 | Min = min; 51 | Max = max; 52 | //can be invalid and might need fix 53 | if (!IsValid) { 54 | Fix(); 55 | } 56 | } 57 | public AABB(Point center,Vector3 extents) { 58 | //min == center - extents, max == c+e 59 | Min.X = center.X - extents.X; 60 | Min.Y = center.Y - extents.Y; 61 | Min.Z = center.Z - extents.Z; 62 | 63 | Max.X = center.X + extents.X; 64 | Max.Y = center.Y + extents.Y; 65 | Max.Z = center.Z + extents.Z; 66 | if (!IsValid) { 67 | Fix(); 68 | } 69 | } 70 | 71 | 72 | public void Render() { 73 | GL.Begin(PrimitiveType.Quads); 74 | 75 | GL.Vertex3(Min.X, Min.Y, Max.Z); 76 | GL.Vertex3(Max.X, Min.Y, Max.Z); 77 | GL.Vertex3(Max.X, Max.Y, Max.Z); 78 | GL.Vertex3(Min.X, Max.Y, Max.Z); 79 | 80 | GL.Vertex3(Max.X, Min.Y, Max.Z); 81 | GL.Vertex3(Max.X, Min.Y, Min.Z); 82 | GL.Vertex3(Max.X, Max.Y, Min.Z); 83 | GL.Vertex3(Max.X, Max.Y, Max.Z); 84 | 85 | GL.Vertex3(Min.X, Max.Y, Max.Z); 86 | GL.Vertex3(Max.X, Max.Y, Max.Z); 87 | GL.Vertex3(Max.X, Max.Y, Min.Z); 88 | GL.Vertex3(Min.X, Max.Y, Min.Z); 89 | 90 | GL.Vertex3(Min.X, Min.Y, Min.Z); 91 | GL.Vertex3(Min.X, Max.Y, Min.Z); 92 | GL.Vertex3(Max.X, Max.Y, Min.Z); 93 | GL.Vertex3(Max.X, Min.Y, Min.Z); 94 | 95 | GL.Vertex3(Min.X, Min.Y, Min.Z); 96 | GL.Vertex3(Max.X, Min.Y, Min.Z); 97 | GL.Vertex3(Max.X, Min.Y, Max.Z); 98 | GL.Vertex3(Min.X, Min.Y, Max.Z); 99 | 100 | GL.Vertex3(Min.X, Min.Y, Min.Z); 101 | GL.Vertex3(Min.X, Min.Y, Max.Z); 102 | GL.Vertex3(Min.X, Max.Y, Max.Z); 103 | GL.Vertex3(Min.X, Max.Y, Min.Z); 104 | 105 | GL.End(); 106 | } 107 | 108 | public override string ToString() { 109 | string result = "Min: (" + Min.X + ", " + Min.Y + ", " + Min.Z + "), "; 110 | result += "Max: ( " + Max.X + ", " + Max.Y + ", " + Max.Z + ")"; 111 | return result; 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/PickingExample.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | using CollisionDetectionSelector; 5 | 6 | namespace CollisionDetectionSelector.Samples { 7 | class SceneSample04 : Application { 8 | Scene scene = new Scene(); 9 | 10 | OBJLoader cube = null; 11 | 12 | Sphere debugSphere = new Sphere(new Point(), 0.5f); 13 | Ray debugRay = new Ray(); 14 | AABB debugBox = null; 15 | 16 | Matrix4 modelView = new Matrix4(); 17 | Matrix4 projection = new Matrix4(); 18 | float[] viewport = new float[4]; 19 | 20 | public override void Initialize(int width, int height) { 21 | GL.Enable(EnableCap.DepthTest); 22 | GL.Enable(EnableCap.Lighting); 23 | GL.Enable(EnableCap.Light0); 24 | GL.PointSize(5f); 25 | 26 | GL.Light(LightName.Light0, LightParameter.Position, new float[] { 0.5f, -0.5f, 0.5f, 0.0f }); 27 | GL.Light(LightName.Light0, LightParameter.Ambient, new float[] { 0f, 1f, 0f, 1f }); 28 | GL.Light(LightName.Light0, LightParameter.Diffuse, new float[] { 0f, 1f, 0f, 1f }); 29 | GL.Light(LightName.Light0, LightParameter.Specular, new float[] { 1f, 1f, 1f, 1f }); 30 | 31 | scene.Initialize(7f); 32 | 33 | cube = new OBJLoader("Assets/cube.obj"); 34 | 35 | // Because the debug AABB we are actually using for picking has no lighting 36 | // let's actually render an OBJ in the exact position of it! 37 | scene.RootObject.Children.Add(new OBJ(cube)); 38 | scene.RootObject.Children[0].Parent = scene.RootObject; 39 | scene.RootObject.Children[0].Position = new Vector3(3f, -7f, -1f); 40 | scene.RootObject.Children[0].Scale = new Vector3(7f, 5f, 4f); 41 | 42 | // Gotta set the World space points of the debug AABB 43 | // to the same thing as the visual node! 44 | Matrix4 world = scene.RootObject.Children[0].WorldMatrix; 45 | debugBox = scene.RootObject.Children[0].BoundingBox; // TEMP 46 | Vector3 newMin = Matrix4.MultiplyPoint(world, debugBox.Min.ToVector()); 47 | Vector3 newMax = Matrix4.MultiplyPoint(world, debugBox.Max.ToVector()); 48 | // Construct the final collision box 49 | debugBox = new AABB(new Point(newMin), new Point(newMax)); 50 | } 51 | 52 | public override void Render() { 53 | base.Render(); 54 | DrawOrigin(); 55 | 56 | GL.Enable(EnableCap.Lighting); 57 | scene.Render(false); 58 | GL.Disable(EnableCap.Lighting); 59 | 60 | float[] rawModelView = new float[16]; 61 | GL.GetFloat(GetPName.ModelviewMatrix, rawModelView); 62 | 63 | float[] rawProjection = new float[16]; 64 | GL.GetFloat(GetPName.ProjectionMatrix, rawProjection); 65 | 66 | GL.GetFloat(GetPName.Viewport, viewport); 67 | 68 | modelView = Matrix4.Transpose(new Matrix4(rawModelView)); 69 | projection = Matrix4.Transpose(new Matrix4(rawProjection)); 70 | 71 | GL.Color3(1f, 0f, 0f); 72 | debugSphere.Render(); 73 | } 74 | 75 | public override void Update(float deltaTime) { 76 | // Don't rotate the scene 77 | //base.Update(deltaTime); 78 | 79 | float[] viewport = new float[] { 0f, 0f, Window.Width, Window.Height }; 80 | 81 | Vector3 near = Matrix4.Unproject(new Vector3(Window.Mouse.X, Window.Mouse.Y, 0.0f), modelView, projection, viewport); 82 | Vector3 far = Matrix4.Unproject(new Vector3(Window.Mouse.X, Window.Mouse.Y, 1.0f), modelView, projection, viewport); 83 | 84 | debugRay = new Ray(near, Vector3.Normalize(far - near)); 85 | Point p = new Point(); 86 | if (LinesAndRays.RaycastAABB(debugRay, debugBox, out p)) { 87 | debugSphere.Position = p; 88 | } 89 | else { 90 | // Off-screen 91 | debugSphere.Position = new Point(-5000, -5000, -5000); 92 | } 93 | } 94 | } 95 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | 28 | # MSTest test Results 29 | [Tt]est[Rr]esult*/ 30 | [Bb]uild[Ll]og.* 31 | 32 | # NUNIT 33 | *.VisualState.xml 34 | TestResult.xml 35 | 36 | # Build Results of an ATL Project 37 | [Dd]ebugPS/ 38 | [Rr]eleasePS/ 39 | dlldata.c 40 | 41 | # DNX 42 | project.lock.json 43 | artifacts/ 44 | 45 | *_i.c 46 | *_p.c 47 | *_i.h 48 | *.ilk 49 | *.meta 50 | *.obj 51 | *.pch 52 | *.pdb 53 | *.pgc 54 | *.pgd 55 | *.rsp 56 | *.sbr 57 | *.tlb 58 | *.tli 59 | *.tlh 60 | *.tmp 61 | *.tmp_proj 62 | *.log 63 | *.vspscc 64 | *.vssscc 65 | .builds 66 | *.pidb 67 | *.svclog 68 | *.scc 69 | 70 | # Chutzpah Test files 71 | _Chutzpah* 72 | 73 | # Visual C++ cache files 74 | ipch/ 75 | *.aps 76 | *.ncb 77 | *.opensdf 78 | *.sdf 79 | *.cachefile 80 | 81 | # Visual Studio profiler 82 | *.psess 83 | *.vsp 84 | *.vspx 85 | 86 | # TFS 2012 Local Workspace 87 | $tf/ 88 | 89 | # Guidance Automation Toolkit 90 | *.gpState 91 | 92 | # ReSharper is a .NET coding add-in 93 | _ReSharper*/ 94 | *.[Rr]e[Ss]harper 95 | *.DotSettings.user 96 | 97 | # JustCode is a .NET coding add-in 98 | .JustCode 99 | 100 | # TeamCity is a build add-in 101 | _TeamCity* 102 | 103 | # DotCover is a Code Coverage Tool 104 | *.dotCover 105 | 106 | # NCrunch 107 | _NCrunch_* 108 | .*crunch*.local.xml 109 | 110 | # MightyMoose 111 | *.mm.* 112 | AutoTest.Net/ 113 | 114 | # Web workbench (sass) 115 | .sass-cache/ 116 | 117 | # Installshield output folder 118 | [Ee]xpress/ 119 | 120 | # DocProject is a documentation generator add-in 121 | DocProject/buildhelp/ 122 | DocProject/Help/*.HxT 123 | DocProject/Help/*.HxC 124 | DocProject/Help/*.hhc 125 | DocProject/Help/*.hhk 126 | DocProject/Help/*.hhp 127 | DocProject/Help/Html2 128 | DocProject/Help/html 129 | 130 | # Click-Once directory 131 | publish/ 132 | 133 | # Publish Web Output 134 | *.[Pp]ublish.xml 135 | *.azurePubxml 136 | ## TODO: Comment the next line if you want to checkin your 137 | ## web deploy settings but do note that will include unencrypted 138 | ## passwords 139 | #*.pubxml 140 | 141 | *.publishproj 142 | 143 | # NuGet Packages 144 | *.nupkg 145 | # The packages folder can be ignored because of Package Restore 146 | **/packages/* 147 | # except build/, which is used as an MSBuild target. 148 | !**/packages/build/ 149 | # Uncomment if necessary however generally it will be regenerated when needed 150 | #!**/packages/repositories.config 151 | 152 | # Windows Azure Build Output 153 | csx/ 154 | *.build.csdef 155 | 156 | # Windows Store app package directory 157 | AppPackages/ 158 | 159 | # Visual Studio cache files 160 | # files ending in .cache can be ignored 161 | *.[Cc]ache 162 | # but keep track of directories ending in .cache 163 | !*.[Cc]ache/ 164 | 165 | # Others 166 | ClientBin/ 167 | [Ss]tyle[Cc]op.* 168 | ~$* 169 | *~ 170 | *.dbmdl 171 | *.dbproj.schemaview 172 | *.pfx 173 | *.publishsettings 174 | node_modules/ 175 | orleans.codegen.cs 176 | 177 | # RIA/Silverlight projects 178 | Generated_Code/ 179 | 180 | # Backup & report files from converting an old project file 181 | # to a newer Visual Studio version. Backup files are not needed, 182 | # because we have git ;-) 183 | _UpgradeReport_Files/ 184 | Backup*/ 185 | UpgradeLog*.XML 186 | UpgradeLog*.htm 187 | 188 | # SQL Server files 189 | *.mdf 190 | *.ldf 191 | 192 | # Business Intelligence projects 193 | *.rdl.data 194 | *.bim.layout 195 | *.bim_*.settings 196 | 197 | # Microsoft Fakes 198 | FakesAssemblies/ 199 | 200 | # Node.js Tools for Visual Studio 201 | .ntvs_analysis.dat 202 | 203 | # Visual Studio 6 build log 204 | *.plg 205 | 206 | # Visual Studio 6 workspace options file 207 | *.opt 208 | 209 | # LightSwitch generated files 210 | GeneratedArtifacts/ 211 | _Pvt_Extensions/ 212 | ModelManifest.xml 213 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/Primitive/Sphere.cs: -------------------------------------------------------------------------------- 1 | using Math_Implementation; 2 | using OpenTK.Graphics.OpenGL; 3 | using System; 4 | 5 | namespace CollisionDetectionSelector.Primitive { 6 | class Sphere { 7 | public float Radius = 1f; 8 | 9 | public Point Position = new Point(); 10 | public Vector3 vPosition { 11 | get { 12 | return Position.Position; 13 | } 14 | } 15 | public Sphere() { 16 | CreateVBO(); 17 | } 18 | public Sphere(Vector3 p, float r) { 19 | Position.X = p.X; 20 | Position.Y = p.Y; 21 | Position.Z = p.Z; 22 | Radius = r; 23 | CreateVBO(); 24 | } 25 | public Sphere(Point p, float r) { 26 | Position.X = p.X; 27 | Position.Y = p.Y; 28 | Position.Z = p.Z; 29 | Radius = r; 30 | CreateVBO(); 31 | } 32 | public Sphere(float x, float y, float z, float r) { 33 | Position.X = x; 34 | Position.Y = y; 35 | Position.Z = z; 36 | Radius = r; 37 | CreateVBO(); 38 | } 39 | 40 | #region Rendering 41 | private float[] verts = null; 42 | private float[] norms = null; 43 | private uint[] indices = null; 44 | 45 | private void CreateVBO(uint rings = 10, uint sectors = 15) { 46 | // From: 47 | // http://stackoverflow.com/questions/5988686/creating-a-3d-sphere-in-opengl-using-visual-c/5989676#5989676 48 | // http://stackoverflow.com/questions/7957254/connecting-sphere-vertices-opengl 49 | float R = 1f / (float)(rings - 1); 50 | float S = 1f / (float)(sectors - 1); 51 | float M_PI = 3.14159265358979323846f; 52 | float M_PI_2 = 1.57079632679489661923f; 53 | 54 | verts = new float[rings * sectors * 3]; 55 | norms = new float[rings * sectors * 3]; 56 | indices = new uint[rings * sectors * 4]; 57 | 58 | int v = 0; 59 | int n = 0; 60 | int i = 0; 61 | 62 | for (int r = 0; r < rings; r++) { 63 | for (int s = 0; s < sectors; s++) { 64 | float y = (float)Math.Sin(-M_PI_2 + M_PI * r * R); 65 | float x = (float)Math.Cos(2f * M_PI * s * S) * (float)Math.Sin(M_PI * r * R); 66 | float z = (float)Math.Sin(2f * M_PI * s * S) * (float)Math.Sin(M_PI * r * R); 67 | 68 | verts[v++] = (x /* * radius*/); 69 | verts[v++] = (y /* * radius*/); 70 | verts[v++] = (z /* * radius*/); 71 | 72 | norms[n++] = (x); 73 | norms[n++] = (y); 74 | norms[n++] = (z); 75 | } 76 | } 77 | 78 | if (v != verts.Length) { 79 | Console.WriteLine("ERROR, Wrong number of verts!"); 80 | } 81 | if (n != norms.Length) { 82 | Console.WriteLine("ERROR, Wrong number of norms!"); 83 | } 84 | 85 | for (int r = 0; r < rings - 1; r++) { 86 | for (int s = 0; s < sectors - 1; s++) { 87 | indices[i++] = ((uint)(r * sectors + s)); 88 | indices[i++] = ((uint)(r * sectors + (s + 1))); 89 | indices[i++] = ((uint)((r + 1) * sectors + (s + 1))); 90 | indices[i++] = ((uint)((r + 1) * sectors + s)); 91 | } 92 | } 93 | 94 | if (i != indices.Length) { 95 | Console.WriteLine("ERROR, Wrong number of indices!"); 96 | } 97 | } 98 | public void Render() { 99 | GL.PushMatrix(); 100 | GL.Translate(Position.X, Position.Y, Position.Z); 101 | GL.Scale(Radius, Radius, Radius); 102 | 103 | GL.EnableClientState(ArrayCap.VertexArray); 104 | GL.EnableClientState(ArrayCap.NormalArray); 105 | 106 | GL.VertexPointer(3, VertexPointerType.Float, 0, verts); 107 | GL.NormalPointer(NormalPointerType.Float, 0, norms); 108 | GL.DrawElements(PrimitiveType.Quads, indices.Length, DrawElementsType.UnsignedInt, indices); 109 | 110 | GL.DisableClientState(ArrayCap.VertexArray); 111 | GL.DisableClientState(ArrayCap.NormalArray); 112 | 113 | GL.PopMatrix(); 114 | } 115 | #endregion 116 | public override string ToString() { 117 | return "Position: (" + Position.X + ", " + Position.Y + ", " + Position.Z + "), Radius: " + Radius; 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/SceneSample.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | using CollisionDetectionSelector; 5 | 6 | namespace CollisionDetectionSelector.Samples { 7 | class SceneSample01 : Application { 8 | Scene scene = new Scene(); 9 | OBJ cubeNode = null; 10 | 11 | OBJLoader suzane = null; 12 | OBJLoader cube = null; 13 | OBJLoader torus = null; 14 | 15 | Ray[] rays = new Ray[] { 16 | new Ray(new Point(0.0f, 0.0f, 0.0f), new Vector3(0.0f, -1.0f, 0.0f)), 17 | new Ray(new Point(-1f, -3f, -5f), new Vector3(0f, 0f, 1f)) 18 | }; 19 | 20 | public override void Initialize(int width, int height) { 21 | GL.Enable(EnableCap.DepthTest); 22 | GL.Enable(EnableCap.CullFace); 23 | GL.Enable(EnableCap.Lighting); 24 | GL.Enable(EnableCap.Light0); 25 | GL.PointSize(5f); 26 | 27 | GL.Light(LightName.Light0, LightParameter.Position, new float[] { 0.0f, 0.5f, 0.5f, 0.0f }); 28 | GL.Light(LightName.Light0, LightParameter.Ambient, new float[] { 0f, 1f, 0f, 1f }); 29 | GL.Light(LightName.Light0, LightParameter.Diffuse, new float[] { 0f, 1f, 0f, 1f }); 30 | GL.Light(LightName.Light0, LightParameter.Specular, new float[] { 1f, 1f, 1f, 1f }); 31 | 32 | suzane = new OBJLoader("Assets/suzanne.obj"); 33 | cube = new OBJLoader("Assets/cube.obj"); 34 | torus = new OBJLoader("Assets/torus.obj"); 35 | 36 | OBJ node = new OBJ(suzane); 37 | node.Parent = scene.RootObject; 38 | node.Parent.Children.Add(node); 39 | node.Position = new Vector3(2.0f, 0.0f, 0.0f); 40 | 41 | node = new OBJ(suzane); 42 | node.Parent = scene.RootObject.Children[0]; // suzane reference 43 | node.Parent.Children.Add(node); 44 | node.Position = new Vector3(-2.0f, -1.0f, 0.0f); 45 | node.Scale = new Vector3(0.5f, 0.5f, 0.5f); 46 | node.Rotation = new Vector3(90.0f, 0f, 0f); 47 | Matrix4 m = node.WorldMatrix; 48 | 49 | node = new OBJ(suzane); 50 | node.Parent = scene.RootObject.Children[0]; // suzane reference 51 | node.Parent.Children.Add(node); 52 | node.Position = new Vector3(0.0f, 0.0f, -2.0f); 53 | node.Rotation = new Vector3(0f, 180f, 0f); 54 | 55 | node = new OBJ(cube); 56 | node.Parent = scene.RootObject; 57 | node.Parent.Children.Add(node); 58 | node.Position = new Vector3(-2.0f, 3.0f, 1.0f); 59 | node.Rotation = new Vector3(45.0f, 0.0f, 0.0f); 60 | cubeNode = node; 61 | 62 | node = new OBJ(torus); 63 | node.Parent = cubeNode; 64 | node.Parent.Children.Add(node); 65 | node.Position = new Vector3(0.0f, 0.0f, -1.0f); 66 | 67 | bool[] b_res = new bool[] { true, false }; 68 | float[] t_res = new float[] { 2.730469f, 0f }; 69 | 70 | float t = 0.0f; 71 | for (int i = 0; i < rays.Length; ++i) { 72 | bool result = scene.Raycast(rays[i], out t) != null; 73 | if (result != b_res[i]) { 74 | System.Console.WriteLine("ray " + i + ", expected: " + b_res[i].ToString() + ", got: " + result.ToString()); 75 | } 76 | if (!CMP(t, t_res[i])) { 77 | System.Console.WriteLine("ray " + i + "t, expected: " + t_res[i].ToString() + ", got: " + t.ToString()); 78 | } 79 | } 80 | } 81 | 82 | bool CMP(float x, float y) { 83 | return System.Math.Abs(x - y) < 0.00001f; 84 | } 85 | 86 | public override void Render() { 87 | base.Render(); 88 | DrawOrigin(); 89 | 90 | GL.Enable(EnableCap.Lighting); 91 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 92 | scene.Render(false); 93 | GL.Disable(EnableCap.Lighting); 94 | 95 | foreach (Ray r in rays) { 96 | if (scene.Raycast(r) != null) { 97 | GL.Color3(1f, 0f, 0f); 98 | } 99 | else { 100 | GL.Color3(0f, 0f, 1f); 101 | } 102 | r.Render(); 103 | } 104 | } 105 | 106 | public override void Update(float deltaTime) { 107 | base.Update(deltaTime); 108 | Vector3 cubeRotation = cubeNode.Rotation; 109 | cubeRotation.X += 45.0f * deltaTime; 110 | cubeNode.Rotation = cubeRotation; 111 | } 112 | } 113 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/BVH.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using OpenTK.Graphics.OpenGL; 5 | using CollisionDetectionSelector.Primitive; 6 | using Math_Implementation; 7 | 8 | class BVHNode { 9 | protected static int maxDepth = 1; 10 | 11 | public List Children = null; 12 | public List Triangles = null; 13 | public AABB AABB = null; 14 | 15 | public int TriangleCount { 16 | get { 17 | int totalCount = 0; 18 | if (Children != null) { 19 | foreach(BVHNode child in Children) { 20 | totalCount += child.TriangleCount; 21 | } 22 | } 23 | else if (Triangles != null) { 24 | totalCount += Triangles.Count; 25 | } 26 | 27 | return totalCount; 28 | } 29 | } 30 | 31 | public BVHNode(AABB aabb) { 32 | //store aabb by value 33 | AABB = new AABB(aabb.Min, aabb.Max); 34 | //assume its leaf by default 35 | Triangles = new List(); 36 | Children = null; 37 | } 38 | public bool IsLeaf { 39 | get { 40 | return Children == null && Triangles != null; 41 | } 42 | } 43 | //Public facing split function 44 | public void Split() { 45 | Split(0); 46 | } 47 | 48 | //private recursive split 49 | protected void Split(int depth) { 50 | //if node is leaf, we can split it 51 | if (IsLeaf) { 52 | //only split if it contains triangles 53 | if (Triangles.Count > 0) { 54 | //only split if were below maximum BVH depth 55 | if (depth < maxDepth) { 56 | Children = new List(); 57 | Vector3 center = AABB.Center.ToVector(); 58 | Vector3 extent = AABB.Extents; 59 | 60 | Vector3 TBR = center + new Vector3(-extent.X, +extent.Y, -extent.Z); 61 | Vector3 TBL = center + new Vector3(+extent.X, +extent.Y, -extent.Z); 62 | Vector3 TFR = center + new Vector3(-extent.X, +extent.Y, +extent.Z); 63 | Vector3 TFL = center + new Vector3(+extent.X, +extent.Y, +extent.Z); 64 | Vector3 BBR = center + new Vector3(-extent.X, -extent.Y, -extent.Z); 65 | Vector3 BBL = center + new Vector3(+extent.X, -extent.Y, -extent.Z); 66 | Vector3 BFR = center + new Vector3(-extent.X, -extent.Y, +extent.Z); 67 | Vector3 BFL = center + new Vector3(+extent.X, -extent.Y, +extent.Z); 68 | 69 | Children.Add(new BVHNode(new AABB(new Point(TFL), new Point(center)))); 70 | Children.Add(new BVHNode(new AABB(new Point(TFR), new Point(center)))); 71 | Children.Add(new BVHNode(new AABB(new Point(TBL), new Point(center)))); 72 | Children.Add(new BVHNode(new AABB(new Point(TBR), new Point(center)))); 73 | Children.Add(new BVHNode(new AABB(new Point(BFL), new Point(center)))); 74 | Children.Add(new BVHNode(new AABB(new Point(BFR), new Point(center)))); 75 | Children.Add(new BVHNode(new AABB(new Point(BBL), new Point(center)))); 76 | Children.Add(new BVHNode(new AABB(new Point(BBR), new Point(center)))); 77 | } 78 | } 79 | } 80 | //if this node was just split, it is neither leaf 81 | //or a normal mode, because it has both triangles and children 82 | //fix by turning into non leaf node 83 | if (Triangles != null && Children != null) { 84 | foreach(Triangle triangle in Triangles) { 85 | foreach(BVHNode child in Children) { 86 | if (Collisions.TriangleAABBIntersect(child.AABB, triangle)) { 87 | child.Triangles.Add(triangle); 88 | } 89 | } 90 | } 91 | //make sure node is not a leaf 92 | Triangles.Clear(); 93 | Triangles = null; 94 | } 95 | 96 | //Splitting is a recursive function, if node isnt a leaf 97 | //split all of leaf nodes ( if possible) 98 | if (Children != null) { 99 | foreach(BVHNode child in Children) { 100 | child.Split(depth + 1); 101 | } 102 | } 103 | } 104 | 105 | public void Shake() { 106 | if (Children != null) { 107 | for (int i = Children.Count-1;i>= 0; i--) { 108 | if (Children[i].TriangleCount == 0) { 109 | Children.RemoveAt(i); 110 | } 111 | } 112 | foreach (BVHNode child in Children) { 113 | child.Shake(); 114 | } 115 | } 116 | } 117 | } 118 | 119 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/OctreeSample.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | using CollisionDetectionSelector; 5 | 6 | namespace CollisionDetectionSelector.Samples { 7 | class SceneSample02 : Application { 8 | Scene scene = new Scene(); 9 | OBJ cubeNode = null; 10 | 11 | OBJLoader suzane = null; 12 | OBJLoader cube = null; 13 | OBJLoader torus = null; 14 | 15 | Ray[] rays = new Ray[] { 16 | new Ray(new Point(0.0f, 0.0f, 0.0f), new Vector3(0.0f, -1.0f, 0.0f)), 17 | new Ray(new Point(-1f, -3f, -5f), new Vector3(0f, 0f, 1f)) 18 | }; 19 | 20 | public override void Initialize(int width, int height) { 21 | GL.Enable(EnableCap.DepthTest); 22 | GL.Enable(EnableCap.CullFace); 23 | GL.Enable(EnableCap.Lighting); 24 | GL.Enable(EnableCap.Light0); 25 | GL.PointSize(5f); 26 | 27 | GL.Light(LightName.Light0, LightParameter.Position, new float[] { 0.0f, 0.5f, 0.5f, 0.0f }); 28 | GL.Light(LightName.Light0, LightParameter.Ambient, new float[] { 0f, 1f, 0f, 1f }); 29 | GL.Light(LightName.Light0, LightParameter.Diffuse, new float[] { 0f, 1f, 0f, 1f }); 30 | GL.Light(LightName.Light0, LightParameter.Specular, new float[] { 1f, 1f, 1f, 1f }); 31 | 32 | scene.Initialize(7f); 33 | 34 | suzane = new OBJLoader("Assets/suzanne.obj"); 35 | cube = new OBJLoader("Assets/cube.obj"); 36 | torus = new OBJLoader("Assets/torus.obj"); 37 | 38 | OBJ node = new OBJ(suzane); 39 | node.Parent = scene.RootObject; 40 | node.Parent.Children.Add(node); 41 | node.Position = new Vector3(2.0f, 0.0f, 0.0f); 42 | /* NEW */ 43 | scene.Octree.Insert(node); 44 | 45 | node = new OBJ(suzane); 46 | node.Parent = scene.RootObject.Children[0]; // suzane reference 47 | node.Parent.Children.Add(node); 48 | node.Position = new Vector3(-2.0f, -1.0f, 0.0f); 49 | node.Scale = new Vector3(0.5f, 0.5f, 0.5f); 50 | node.Rotation = new Vector3(90.0f, 0f, 0f); 51 | /* NEW */ 52 | scene.Octree.Insert(node); 53 | 54 | node = new OBJ(suzane); 55 | node.Parent = scene.RootObject.Children[0]; // suzane reference 56 | node.Parent.Children.Add(node); 57 | node.Position = new Vector3(0.0f, 0.0f, -2.0f); 58 | node.Rotation = new Vector3(0f, 180f, 0f); 59 | /* NEW */ 60 | scene.Octree.Insert(node); 61 | 62 | node = new OBJ(cube); 63 | node.Parent = scene.RootObject; 64 | node.Parent.Children.Add(node); 65 | node.Position = new Vector3(-2.0f, 3.0f, 1.0f); 66 | node.Rotation = new Vector3(45.0f, 0.0f, 0.0f); 67 | cubeNode = node; 68 | /* NEW */ 69 | scene.Octree.Insert(node); 70 | 71 | node = new OBJ(torus); 72 | node.Parent = cubeNode; 73 | node.Parent.Children.Add(node); 74 | node.Position = new Vector3(0.0f, 0.0f, -1.0f); 75 | /* NEW */ 76 | scene.Octree.Insert(node); 77 | 78 | bool[] b_res = new bool[] { true, false }; 79 | float[] t_res = new float[] { 2.730469f, 0f }; 80 | 81 | float t = 0.0f; 82 | for (int i = 0; i < rays.Length; ++i) { 83 | bool result = scene.Raycast(rays[i], out t) != null; 84 | if (result != b_res[i]) { 85 | System.Console.WriteLine("ray " + i + ", expected: " + b_res[i].ToString() + ", got: " + result.ToString()); 86 | } 87 | if (!CMP(t, t_res[i])) { 88 | System.Console.WriteLine("ray " + i + "t, expected: " + t_res[i].ToString() + ", got: " + t.ToString()); 89 | } 90 | } 91 | } 92 | 93 | bool CMP(float x, float y) { 94 | return System.Math.Abs(x - y) < 0.00001f; 95 | } 96 | 97 | public override void Render() { 98 | base.Render(); 99 | DrawOrigin(); 100 | 101 | GL.Enable(EnableCap.Lighting); 102 | scene.Render(true); 103 | GL.Disable(EnableCap.Lighting); 104 | 105 | foreach (Ray r in rays) { 106 | if (scene.Raycast(r) != null) { 107 | GL.Color3(1f, 0f, 0f); 108 | } 109 | else { 110 | GL.Color3(0f, 0f, 1f); 111 | } 112 | r.Render(); 113 | } 114 | } 115 | 116 | public override void Update(float deltaTime) { 117 | base.Update(deltaTime); 118 | Vector3 cubeRotation = cubeNode.Rotation; 119 | cubeRotation.X += 45.0f * deltaTime; 120 | cubeNode.Rotation = cubeRotation; 121 | 122 | /* NEW */ 123 | scene.Octree.Update(cubeNode); 124 | } 125 | } 126 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/AABBPointSample.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class AABBPointSample : Application { 7 | protected Vector3 cameraAngle = new Vector3(120.0f, -10f, 20.0f); 8 | protected float rads = (float)(System.Math.PI / 180.0f); 9 | 10 | AABB[] testAABBs = new AABB[] { 11 | new AABB(new Point(2f, 4f, 0f), new Vector3(1f, 2f, 3f)), 12 | new AABB(new Point(-0.5f, -0.5f, -0.5f), new Point(0.5f, 0.5f, 0.5f)) 13 | }; 14 | 15 | Point[] testPoints = new Point[] { 16 | new Point(0.2f, -0.2f, 0.2f), 17 | new Point(1f, 1f, 1f), 18 | new Point(-0.5f, 0.5f, -0.5f), 19 | new Point(2f, 4f, 0f), 20 | new Point(2f, 0f, 0f), 21 | new Point(2f, 4f, 6.5f), 22 | }; 23 | 24 | Point farPoint = new Point(-1f, 3f, 1.5f); 25 | Point secondFarPoint = new Point(2f, 3.4f, 1f); 26 | 27 | public override void Initialize(int width, int height) { 28 | // Seeing the back face of a square gives a better 29 | // overview of the actual geometry 30 | //GL.Enable(EnableCap.CullFace); 31 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 32 | GL.PointSize(2f); 33 | 34 | Point closest = Collisions.ClosestPoint(testAABBs[0], secondFarPoint); 35 | if (closest.ToVector() != new Vector3(2f, 3.4f, 1f)) { 36 | System.Console.ForegroundColor = System.ConsoleColor.Red; 37 | } 38 | System.Console.WriteLine("closest: " + closest + " / 2, 3.4, 1"); 39 | System.Console.ResetColor(); 40 | } 41 | 42 | public override void Render() { 43 | Vector3 eyePos = new Vector3(); 44 | eyePos.X = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 45 | eyePos.Y = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.Y * rads); 46 | eyePos.Z = -cameraAngle.Z * (float)System.Math.Cos(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 47 | 48 | Matrix4 lookAt = Matrix4.LookAt(eyePos, new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f)); 49 | GL.LoadMatrix(Matrix4.Transpose(lookAt).Matrix); 50 | 51 | DrawOrigin(); 52 | 53 | GL.Color3(1f, 1f, 1f); 54 | foreach (AABB aabb in testAABBs) { 55 | aabb.Render(); 56 | } 57 | 58 | foreach (Point point in testPoints) { 59 | bool collides = false; 60 | foreach (AABB aabb in testAABBs) { 61 | if (Collisions.PointInAABB(aabb, point)) { 62 | collides = true; 63 | break; 64 | } 65 | } 66 | 67 | if (collides) { 68 | GL.Color3(1f, 0f, 0f); 69 | } 70 | else { 71 | GL.Color3(0f, 1f, 0f); 72 | } 73 | point.Render(); 74 | } 75 | 76 | Point closest; 77 | foreach (AABB aabb in testAABBs) { 78 | closest = Collisions.ClosestPoint(aabb, farPoint); 79 | 80 | GL.Color3(0f, 1f, 1f); 81 | GL.Begin(PrimitiveType.Lines); 82 | GL.Vertex3(closest.X, closest.Y, closest.Z); 83 | GL.Vertex3(farPoint.X, farPoint.Y, farPoint.Z); 84 | GL.End(); 85 | 86 | GL.Color3(1f, 1f, 0f); 87 | closest.Render(); 88 | } 89 | 90 | GL.Color3(0f, 0f, 1f); 91 | farPoint.Render(); 92 | secondFarPoint.Render(); 93 | 94 | closest = Collisions.ClosestPoint(testAABBs[0], secondFarPoint); 95 | GL.Color3(0f, 1f, 1f); 96 | GL.Begin(PrimitiveType.Lines); 97 | GL.Vertex3(closest.X, closest.Y, closest.Z); 98 | GL.Vertex3(secondFarPoint.X, secondFarPoint.Y, secondFarPoint.Z); 99 | GL.End(); 100 | 101 | GL.Color3(1f, 1f, 0f); 102 | closest.Render(); 103 | } 104 | 105 | public override void Update(float deltaTime) { 106 | cameraAngle.X += 45.0f * deltaTime; 107 | } 108 | 109 | protected void DrawOrigin() { 110 | GL.Begin(PrimitiveType.Lines); 111 | GL.Color3(1f, 0f, 0f); 112 | GL.Vertex3(0f, 0f, 0f); 113 | GL.Vertex3(1f, 0f, 0f); 114 | GL.Color3(0f, 1f, 0f); 115 | GL.Vertex3(0f, 0f, 0f); 116 | GL.Vertex3(0f, 1f, 0f); 117 | GL.Color3(0f, 0f, 1f); 118 | GL.Vertex3(0f, 0f, 0f); 119 | GL.Vertex3(0f, 0f, 1f); 120 | GL.End(); 121 | } 122 | 123 | public override void Resize(int width, int height) { 124 | GL.Viewport(0, 0, width, height); 125 | GL.MatrixMode(MatrixMode.Projection); 126 | float aspect = (float)width / (float)height; 127 | Matrix4 perspective = Matrix4.Perspective(60, aspect, 0.01f, 1000.0f); 128 | GL.LoadMatrix(Matrix4.Transpose(perspective).Matrix); 129 | GL.MatrixMode(MatrixMode.Modelview); 130 | GL.LoadIdentity(); 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/ClosestPointSample.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class ClosestPointSample : Application { 7 | protected Vector3 cameraAngle = new Vector3(120.0f, -10f, 20.0f); 8 | protected float rads = (float)(System.Math.PI / 180.0f); 9 | 10 | Point[] testPoints = new Point[] { 11 | new Point(1, 0, 0), 12 | new Point(0, 1, 0), 13 | new Point(0, 0, 1), 14 | new Point(0.5f, 0.5f, 0.5f), 15 | new Point(2f, 2f, 2f), 16 | new Point(3f, 3f, 3f), 17 | new Point(4f, 4f, 4f), 18 | }; 19 | 20 | Point farPoint = new Point(0f, 0f, 7f); 21 | Sphere testSphere = new Sphere(1f, 1f, 0f, 2f); 22 | 23 | public override void Initialize(int width, int height) { 24 | GL.Enable(EnableCap.CullFace); 25 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 26 | GL.PointSize(2f); 27 | 28 | bool[] results = new bool[] { true, true, true, true, false, false, false }; 29 | for (int i = 0; i < testPoints.Length; ++i) { 30 | bool collision = Collisions.PointInSphere(testSphere, testPoints[i]); 31 | if (collision != results[i]) { 32 | System.Console.ForegroundColor = System.ConsoleColor.Red; 33 | } 34 | System.Console.Write("Point: " + testPoints[i]); 35 | if (collision) { 36 | System.Console.WriteLine(" is in sphere"); 37 | } 38 | else { 39 | System.Console.WriteLine(" is not in sphere"); 40 | } 41 | System.Console.ResetColor(); 42 | } 43 | 44 | Vector3 expected = new Vector3(0.719944f, 0.719944f, 1.960392f); 45 | Point closest = Collisions.ClosestPoint(testSphere, farPoint); 46 | if (expected != closest.ToVector()) { 47 | System.Console.ForegroundColor = System.ConsoleColor.Red; 48 | } 49 | System.Console.WriteLine("Closest point: " + closest); 50 | if (expected != closest.ToVector()) { 51 | System.Console.WriteLine("Expected: " + expected.X + ", " + expected.Y + ", " + expected.Z); 52 | } 53 | System.Console.ResetColor(); 54 | } 55 | 56 | public override void Render() { 57 | Vector3 eyePos = new Vector3(); 58 | eyePos.X = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 59 | eyePos.Y = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.Y * rads); 60 | eyePos.Z = -cameraAngle.Z * (float)System.Math.Cos(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 61 | 62 | Matrix4 lookAt = Matrix4.LookAt(eyePos, new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f)); 63 | GL.LoadMatrix(Matrix4.Transpose(lookAt).Matrix); 64 | 65 | DrawOrigin(); 66 | 67 | GL.Color3(1f, 1f, 1f); 68 | testSphere.Render(); 69 | 70 | foreach (Point point in testPoints) { 71 | if (Collisions.PointInSphere(testSphere, point)) { 72 | GL.Color3(1f, 0f, 0f); 73 | } 74 | else { 75 | GL.Color3(0f, 1f, 0f); 76 | } 77 | point.Render(); 78 | } 79 | 80 | GL.Color3(0f, 0f, 1f); 81 | farPoint.Render(); 82 | 83 | Point closest = Collisions.ClosestPoint(testSphere, farPoint); 84 | GL.Color3(1f, 0f, 1f); 85 | GL.Begin(PrimitiveType.Lines); 86 | GL.Vertex3(testSphere.Position.X, testSphere.Position.Y, testSphere.Position.Z); 87 | GL.Vertex3(closest.X, closest.Y, closest.Z); 88 | GL.End(); 89 | 90 | GL.Color3(1f, 1f, 0f); 91 | closest.Render(); 92 | 93 | GL.Color3(0f, 1f, 1f); 94 | GL.Begin(PrimitiveType.Lines); 95 | GL.Vertex3(closest.X, closest.Y, closest.Z); 96 | GL.Vertex3(farPoint.X, farPoint.Y, farPoint.Z); 97 | GL.End(); 98 | } 99 | 100 | public override void Update(float deltaTime) { 101 | cameraAngle.X += 45.0f * deltaTime; 102 | } 103 | 104 | protected void DrawOrigin() { 105 | GL.Begin(PrimitiveType.Lines); 106 | GL.Color3(1f, 0f, 0f); 107 | GL.Vertex3(0f, 0f, 0f); 108 | GL.Vertex3(1f, 0f, 0f); 109 | GL.Color3(0f, 1f, 0f); 110 | GL.Vertex3(0f, 0f, 0f); 111 | GL.Vertex3(0f, 1f, 0f); 112 | GL.Color3(0f, 0f, 1f); 113 | GL.Vertex3(0f, 0f, 0f); 114 | GL.Vertex3(0f, 0f, 1f); 115 | GL.End(); 116 | } 117 | 118 | public override void Resize(int width, int height) { 119 | GL.Viewport(0, 0, width, height); 120 | GL.MatrixMode(MatrixMode.Projection); 121 | float aspect = (float)width / (float)height; 122 | Matrix4 perspective = Matrix4.Perspective(60, aspect, 0.01f, 1000.0f); 123 | GL.LoadMatrix(Matrix4.Transpose(perspective).Matrix); 124 | GL.MatrixMode(MatrixMode.Modelview); 125 | GL.LoadIdentity(); 126 | } 127 | } 128 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Application.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using OpenTK; 3 | using System.Drawing; 4 | using OpenTK.Graphics.OpenGL; 5 | 6 | public class Application { 7 | public static Application Instance { 8 | get; private set; 9 | } 10 | public OpenTK.GameWindow Window = null; 11 | private Math_Implementation.Vector3 _baseCameraAngle = new Math_Implementation.Vector3(120.0f, -10.0f, 20.0f); 12 | private float _baseRads = (float)(System.Math.PI / 180.0f); 13 | 14 | public Application() { 15 | Instance = this; 16 | } 17 | 18 | #region CommonMethods 19 | public void LogError(string error) { 20 | Console.ForegroundColor = ConsoleColor.Red; 21 | Console.WriteLine("Error: " + error); 22 | Console.ResetColor(); 23 | } 24 | 25 | public void DrawOrigin() { 26 | GL.Begin(PrimitiveType.Lines); 27 | GL.Color3(1f, 0f, 0f); 28 | GL.Vertex3(0f, 0f, 0f); 29 | GL.Vertex3(1f, 0f, 0f); 30 | GL.Color3(0f, 1f, 0f); 31 | GL.Vertex3(0f, 0f, 0f); 32 | GL.Vertex3(0f, 1f, 0f); 33 | GL.Color3(0f, 0f, 1f); 34 | GL.Vertex3(0f, 0f, 0f); 35 | GL.Vertex3(0f, 0f, 1f); 36 | GL.End(); 37 | } 38 | #endregion 39 | 40 | //logic driving functions that are overwritten 41 | #region InheritableLogic 42 | public virtual void Initialize(int width,int height) { 43 | 44 | } 45 | 46 | public virtual void Update(float dTime) { 47 | _baseCameraAngle.X += 45.0f * dTime; 48 | } 49 | public virtual void Render() { 50 | // Again, Vector3 and Matrix4 must be fully scoped, because 51 | // the OpenTK namespace contains both classes already 52 | Math_Implementation.Vector3 eyePos = new Math_Implementation.Vector3(); 53 | eyePos.X = _baseCameraAngle.Z * -(float)System.Math.Sin(_baseCameraAngle.X * _baseRads * (float)System.Math.Cos(_baseCameraAngle.Y * _baseRads)); 54 | eyePos.Y = _baseCameraAngle.Z * -(float)System.Math.Sin(_baseCameraAngle.Y * _baseRads); 55 | eyePos.Z = -_baseCameraAngle.Z * (float)System.Math.Cos(_baseCameraAngle.X * _baseRads * (float)System.Math.Cos(_baseCameraAngle.Y * _baseRads)); 56 | 57 | Math_Implementation.Matrix4 lookAt = 58 | Math_Implementation.Matrix4.LookAt(eyePos, 59 | new Math_Implementation.Vector3(0.0f, 0.0f, 0.0f), 60 | new Math_Implementation.Vector3(0.0f, 1.0f, 0.0f)); 61 | GL.LoadMatrix(Math_Implementation.Matrix4.Transpose(lookAt).Matrix); 62 | } 63 | public virtual void Shutdown() { 64 | 65 | } 66 | // Has a default implementation, making the need to override in child 67 | // classes purley optional 68 | public virtual void Resize(int width, int height) { 69 | GL.Viewport(0, 0, width, height); 70 | GL.MatrixMode(MatrixMode.Projection); 71 | float aspect = (float)width / (float)height; 72 | Math_Implementation.Matrix4 perspective = 73 | Math_Implementation.Matrix4.Perspective(60, aspect, 0.01f, 1000.0f); 74 | GL.LoadMatrix(Math_Implementation.Matrix4.Transpose(perspective).Matrix); 75 | GL.MatrixMode(MatrixMode.Modelview); 76 | GL.LoadIdentity(); 77 | } 78 | #endregion 79 | 80 | #region EntryPoint 81 | 82 | //entry point of application, not overwritten 83 | public virtual void Main(string[] args) { 84 | Window = new OpenTK.GameWindow(); 85 | Window.Load += new EventHandler(OpenTKInitialize); 86 | Window.UpdateFrame += new EventHandler(OpenTKUpdate); 87 | Window.RenderFrame += new EventHandler(OpenTKRender); 88 | Window.Unload += new EventHandler(OpenTKShutdown); 89 | Window.Title = "Sample Application"; 90 | Window.ClientSize = new System.Drawing.Size(800, 600); 91 | Instance.Resize(800, 600); 92 | Window.VSync = VSyncMode.On; 93 | Window.Run(60.0f); 94 | Window.Dispose(); 95 | } 96 | 97 | #endregion 98 | 99 | // if default entry point, default functions 100 | #region OpenTKCallbacks 101 | 102 | private void OpenTKInitialize(object sender, EventArgs e) { 103 | Console.Clear(); 104 | Console.ForegroundColor = ConsoleColor.DarkGray; 105 | Console.WriteLine("OpenGL Vendor: " + GL.GetString(StringName.Vendor)); 106 | Console.WriteLine("OpenGL Renderer: " + GL.GetString(StringName.Renderer)); 107 | Console.WriteLine("OpenGL Version: " + GL.GetString(StringName.Version)); 108 | Console.ResetColor(); 109 | Instance.Initialize(800, 600); 110 | } 111 | 112 | private void OpenTKUpdate(object sender, FrameEventArgs e) { 113 | float dTime = (float)e.Time; 114 | Instance.Update(dTime); 115 | } 116 | 117 | private void OpenTKRender(object sender, FrameEventArgs e) { 118 | GL.ClearColor(Color.CadetBlue); 119 | GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit); 120 | Instance.Render(); 121 | Window.SwapBuffers(); 122 | } 123 | 124 | private void OpenTKShutdown(object sender, EventArgs e) { 125 | Instance.Shutdown(); 126 | } 127 | 128 | private void OpenTKResize(EventArgs e) { 129 | Instance.Resize(Instance.Window.Width, Instance.Window.Height); 130 | } 131 | #endregion 132 | 133 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/PointOnPlaneSample.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class PointOnPlaneSample : Application { 7 | protected Vector3 cameraAngle = new Vector3(120.0f, -10f, 20.0f); 8 | protected float rads = (float)(System.Math.PI / 180.0f); 9 | 10 | Plane plane = new Plane(new Point(5, 6, 7), new Point(6, 5, 4), new Point(1, 2, 3)); 11 | Point[] points = new Point[] { 12 | new Point(0f, 0f, 0f), 13 | new Point(2f, 6f, 1f), 14 | new Point(3f, 1f, -3f), 15 | new Point(-2f, -1f, 2f), 16 | new Point(7f, 7f, -7f), 17 | new Point(3f, 2f, -1f), 18 | new Point(10f, 3f, -10f), 19 | new Point(2f, 8f, -7f), 20 | new Point(-1.632993f, 3.265986f, -1.632993f), 21 | new Point(-1.020621f, 3.265986f, -2.245366f) 22 | }; 23 | 24 | public override void Initialize(int width, int height) { 25 | GL.Enable(EnableCap.DepthTest); 26 | GL.PointSize(2f); 27 | plane.Distance = 4f; 28 | 29 | int[] expected = new int[] { -1, -1, -1, -1, 1, -1, -1, 1, 0, 0 }; 30 | int[] result = new int[] { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }; 31 | 32 | if (expected.Length != result.Length) { 33 | System.Console.ForegroundColor = System.ConsoleColor.Red; 34 | System.Console.WriteLine("Gabor messed up!"); 35 | } 36 | 37 | if (result.Length != points.Length) { 38 | System.Console.ForegroundColor = System.ConsoleColor.Red; 39 | System.Console.WriteLine("Gabor messed up!"); 40 | } 41 | 42 | for (int i = 0; i < points.Length; ++i) { 43 | Point point = points[i]; 44 | if (Collisions.PointOnPlane(point, plane)) { 45 | result[i] = 0; 46 | } 47 | else { 48 | if (Collisions.DistanceFromPlane(point, plane) < 0f) { 49 | result[i] = -1; 50 | } 51 | else { 52 | result[i] = 1; 53 | } 54 | } 55 | } 56 | 57 | for (int i = 0; i < points.Length; ++i) { 58 | if (result[i] == 3) { 59 | System.Console.ForegroundColor = System.ConsoleColor.Red; 60 | System.Console.WriteLine("Gabor messed up!"); 61 | } 62 | 63 | if (expected[i] != result[i]) { 64 | System.Console.ForegroundColor = System.ConsoleColor.Red; 65 | System.Console.Write("Point " + i + " was expected "); 66 | if (expected[i] == 0) { 67 | System.Console.Write("on "); 68 | } 69 | else if (expected[i] == 1) { 70 | System.Console.Write("in front of "); 71 | } 72 | else if (expected[i] == -1) { 73 | System.Console.Write("behind the "); 74 | } 75 | System.Console.Write("plane, but was found "); 76 | if (result[i] == 0) { 77 | System.Console.Write("on"); 78 | } 79 | else if (result[i] == 1) { 80 | System.Console.Write("in front"); 81 | } 82 | else if (result[i] == -1) { 83 | System.Console.Write("behind"); 84 | } 85 | System.Console.WriteLine("\n\tPlane: " + plane.ToString()); 86 | System.Console.WriteLine("\tPoint: " + points[i].ToString() + "\n"); 87 | } 88 | } 89 | } 90 | 91 | public override void Render() { 92 | Vector3 eyePos = new Vector3(); 93 | eyePos.X = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 94 | eyePos.Y = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.Y * rads); 95 | eyePos.Z = -cameraAngle.Z * (float)System.Math.Cos(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 96 | 97 | Matrix4 lookAt = Matrix4.LookAt(eyePos, new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f)); 98 | GL.LoadMatrix(Matrix4.Transpose(lookAt).Matrix); 99 | 100 | DrawOrigin(); 101 | 102 | GL.Color3(1f, 1f, 1f); 103 | plane.Render(7f); 104 | 105 | foreach (Point point in points) { 106 | if (Collisions.PointOnPlane(point, plane)) { 107 | GL.Color3(0f, 1f, 0f); 108 | } 109 | else { 110 | if (Collisions.DistanceFromPlane(point, plane) < 0f) { 111 | GL.Color3(1f, 0f, 0f); 112 | } 113 | else { 114 | GL.Color3(0f, 0f, 1f); 115 | } 116 | } 117 | point.Render(); 118 | } 119 | } 120 | 121 | public override void Update(float deltaTime) { 122 | cameraAngle.X += 45.0f * deltaTime; 123 | } 124 | 125 | protected void DrawOrigin() { 126 | GL.Begin(PrimitiveType.Lines); 127 | GL.Color3(1f, 0f, 0f); 128 | GL.Vertex3(0f, 0f, 0f); 129 | GL.Vertex3(1f, 0f, 0f); 130 | GL.Color3(0f, 1f, 0f); 131 | GL.Vertex3(0f, 0f, 0f); 132 | GL.Vertex3(0f, 1f, 0f); 133 | GL.Color3(0f, 0f, 1f); 134 | GL.Vertex3(0f, 0f, 0f); 135 | GL.Vertex3(0f, 0f, 1f); 136 | GL.End(); 137 | } 138 | 139 | public override void Resize(int width, int height) { 140 | GL.Viewport(0, 0, width, height); 141 | GL.MatrixMode(MatrixMode.Projection); 142 | float aspect = (float)width / (float)height; 143 | Matrix4 perspective = Matrix4.Perspective(60, aspect, 0.01f, 1000.0f); 144 | GL.LoadMatrix(Matrix4.Transpose(perspective).Matrix); 145 | GL.MatrixMode(MatrixMode.Modelview); 146 | GL.LoadIdentity(); 147 | } 148 | } 149 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Math/Vector4.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | 4 | namespace Math_Implementation { 5 | class Vector4 { 6 | public float X = 0.0f; 7 | public float Y = 0.0f; 8 | public float Z = 0.0f; 9 | public float W = 0.0f; 10 | public float this[int i] { 11 | get { 12 | if (i == 0) { 13 | return X; 14 | } 15 | else if (i == 1) { 16 | return Y; 17 | } 18 | else if (i == 2) { 19 | return Z; 20 | } 21 | else if (i == 3) { 22 | return W; 23 | } 24 | return 0; 25 | } 26 | set { 27 | if (i == 0) { 28 | X = value; 29 | } 30 | else if (i == 1) { 31 | Y = value; 32 | } 33 | else if (i == 2) { 34 | Z = value; 35 | } 36 | else if (i == 3) { 37 | W = value; 38 | } 39 | } 40 | } 41 | public Vector4() { 42 | X = Y = Z = W = 0.0f; 43 | } 44 | public Vector4(float x,float y,float z, float w) { 45 | X = x; 46 | Y = y; 47 | Z = z; 48 | W = w; 49 | } 50 | public static Vector4 operator +(Vector4 vectorA,Vector4 vectorB) { 51 | return new Vector4(vectorA.X + vectorB.X, vectorA.Y + vectorB.Y, vectorA.Z + vectorB.Z, vectorA.W + vectorB.W); 52 | } 53 | public static Vector4 operator -(Vector4 vectorA, Vector4 vectorB) { 54 | return new Vector4(vectorA.X - vectorB.X, vectorA.Y - vectorB.Y, vectorA.Z - vectorB.Z, vectorA.W - vectorB.W); 55 | } 56 | public static Vector4 operator *(Vector4 vectorA, Vector4 vectorB) { 57 | return new Vector4(vectorA.X * vectorB.X, vectorA.Y * vectorB.Y, vectorA.Z * vectorB.Z, vectorA.W * vectorB.W); 58 | } 59 | public static Vector4 operator *(Vector4 vectorA, float scale) { 60 | return new Vector4(vectorA.X * scale, vectorA.Y * scale, vectorA.Z * scale, vectorA.W * scale); 61 | } 62 | public static Vector4 operator /(Vector4 vectorA, Vector4 vectorB) { 63 | return new Vector4(vectorA.X / vectorB.X, vectorA.Y / vectorB.Y, vectorA.Z / vectorB.Z, vectorA.W / vectorB.W); 64 | } 65 | public static float Dot(Vector4 vectorA,Vector4 vectorB) { 66 | float x = vectorA.X * vectorB.X; 67 | float y = vectorA.Y * vectorB.Y; 68 | float z = vectorA.Z * vectorB.Z; 69 | return x + y + z; 70 | } 71 | public float Dot(Vector4 vectorA) { 72 | float x = vectorA.X * X; 73 | float y = vectorA.Y * Y; 74 | float z = vectorA.Z * Z; 75 | return x + y + z; 76 | } 77 | public static float Length(Vector4 vectorA) { 78 | return (float)Math.Sqrt(Dot(vectorA, vectorA)); 79 | } 80 | public float Length() { 81 | return (float)Math.Sqrt(Dot(this, this)); 82 | } 83 | public static float LengthSquared(Vector4 vectorA) { 84 | return Dot(vectorA, vectorA); 85 | } 86 | public float LengthSquared() { 87 | return Dot(this, this); 88 | } 89 | public static Vector4 Normalize(Vector4 vectorA) { 90 | float length = Length(vectorA); 91 | return new Vector4(vectorA.X / length, vectorA.Y / length, vectorA.Z / length, vectorA.Z); 92 | } 93 | public void Normalize() { 94 | float length = Length(this); 95 | X /= length; 96 | Y /= length; 97 | Z /= length; 98 | } 99 | public static float AngleBetween(Vector4 vectorA,Vector4 vectorB) { 100 | return (float)Math.Acos(Dot(Normalize(vectorA), Normalize(vectorB))); 101 | } 102 | public float AngleBetween(Vector4 vectorA) { 103 | return (float)Math.Acos(Dot(Normalize(vectorA), Normalize(this))); 104 | } 105 | public static Vector4 Projection(Vector4 vectorA,Vector4 vectorB) { 106 | float projectionLength = Dot(vectorA, vectorB) / Length(vectorB); 107 | return Normalize(vectorB) * projectionLength; 108 | } 109 | public static Vector4 Perpendicular(Vector4 vectorA,Vector4 vectorB) { 110 | return vectorB-Projection(vectorA, vectorB); 111 | } 112 | public static Vector4 Cross(Vector4 vectorA,Vector4 vectorB) { 113 | Vector4 result = new Vector4(); 114 | result.X = (vectorA.Y * vectorB.Z) - (vectorA.Z * vectorB.Y ); 115 | result.Y = (vectorA.Z * vectorB.X) - (vectorA.X * vectorB.Z ); 116 | result.Z = (vectorA.X * vectorB.Y) - (vectorA.Y * vectorB.X ); 117 | return result; 118 | } 119 | public static Vector4 Negate(Vector4 vectorA) { 120 | return new Vector4(vectorA.X *= -1, vectorA.Y * -1, vectorA.Z * -1,vectorA.W); 121 | } 122 | public void Negate() { 123 | X *= -1; 124 | Y *= -1; 125 | Z *= -1; 126 | } 127 | public static bool Fequal(float a, float b) { 128 | return Math.Abs(a - b) < 0.0001; 129 | } 130 | public static bool operator ==(Vector4 vectorA, Vector4 vectorB) { 131 | return Fequal(vectorA.X,vectorB.X) && Fequal(vectorA.Y,vectorB.Y) && Fequal(vectorA.Z,vectorB.Z) ? true : false; 132 | } 133 | public static bool operator !=(Vector4 vectorA, Vector4 vectorB) { 134 | return !Fequal(vectorA.X,vectorB.X) || !Fequal(vectorA.Y,vectorB.Y) || !Fequal(vectorA.Z,vectorB.Z) ? true : false; 135 | } 136 | public static bool operator >=(Vector4 vectorA, Vector4 vectorB) { 137 | return vectorA.LengthSquared() >= vectorB.LengthSquared() ? true : false; 138 | } 139 | public static bool operator <=(Vector4 vectorA, Vector4 vectorB) { 140 | return vectorA.LengthSquared() <= vectorB.LengthSquared() ? true : false; 141 | } 142 | public static bool operator <(Vector4 vectorA, Vector4 vectorB) { 143 | return vectorA.LengthSquared() < vectorB.LengthSquared() ? true : false; 144 | } 145 | public static bool operator >(Vector4 vectorA, Vector4 vectorB) { 146 | return vectorA.LengthSquared() > vectorB.LengthSquared() ? true : false; 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/Primitive/Camera.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using OpenTK.Graphics.OpenGL; 3 | using Math_Implementation; 4 | 5 | namespace CollisionDetectionSelector.Primitive { 6 | class Camera { 7 | //members to hold position and orientation 8 | protected Vector3 position = new Vector3(0f, 0f, 0f); 9 | protected Vector3 forward = new Vector3(0f, 0f, 1f); 10 | protected Vector3 right = new Vector3(1f, 0f, 0f); 11 | protected Vector3 up = new Vector3(0f, 1f, 0f); 12 | 13 | //cached matrices to avoid work every frame 14 | protected bool worldDirty = true; 15 | protected bool viewDirty = true; 16 | protected Matrix4 cachedWorld = new Matrix4(); 17 | protected Matrix4 cachedView = new Matrix4(); 18 | 19 | public Matrix4 ProjectionMatrix { 20 | get { 21 | float[] rawPorjection = new float[16]; 22 | GL.GetFloat(GetPName.ProjectionMatrix, rawPorjection); 23 | return Matrix4.Transpose(new Matrix4(rawPorjection)); 24 | } 25 | } 26 | public Matrix4 Translation { 27 | get { 28 | //Identity, with 4th column being positions 29 | return new Matrix4(1f, 0f, 0f, position.X, 30 | 0f, 1f, 0f, position.Y, 31 | 0f, 0f, 1f, position.Z, 32 | 0f, 0f, 0f, 1f); 33 | } 34 | } 35 | public Matrix4 Orientation { 36 | get { 37 | //return orientation matrix 38 | return new Matrix4(right.X,up.X,-forward.X,0f, 39 | right.Y,up.Y,-forward.Y,0f, 40 | right.Z,up.Z,-forward.Z,0f, 41 | 0f, 0f, 0f, 1f 42 | ); 43 | } 44 | } 45 | public Matrix4 WorldMatrix { 46 | get { 47 | if (worldDirty) { 48 | //post multiplication 49 | //rotate, translate, always reverse order 50 | cachedWorld = Translation * Orientation; 51 | } 52 | worldDirty = false; 53 | return cachedWorld; 54 | } 55 | } 56 | public Matrix4 ViewMatrix { 57 | get { 58 | if (viewDirty) { 59 | cachedView = Matrix4.Inverse(WorldMatrix); 60 | } 61 | viewDirty = false; 62 | return cachedView; 63 | } 64 | } 65 | #region READONLY 66 | public Point Position { 67 | get { 68 | return new Point(position.X, position.Y, position.Z); 69 | } 70 | } 71 | public Vector3 Forward { 72 | get { 73 | return new Vector3(forward.X, forward.Y, forward.Z); 74 | } 75 | } 76 | public Vector3 Right { 77 | get { 78 | return new Vector3(right.X, right.Y, right.Z); 79 | } 80 | } 81 | public Vector3 Up { 82 | get { 83 | return new Vector3(up.X, up.Y, up.Z); 84 | } 85 | } 86 | #endregion 87 | //same as matrix4.LookAt 88 | public void LookAt(Vector3 camPos, Vector3 camTarget, Vector3 camUp) { 89 | worldDirty = true; 90 | viewDirty = true; 91 | 92 | forward = Vector3.Normalize(camTarget - camPos); 93 | right = Vector3.Normalize(Vector3.Cross(forward, camUp)); 94 | up = Vector3.Cross(right, forward); 95 | 96 | //set to a copy not reference 97 | position = new Vector3(camPos.X, camPos.Y, camPos.Z); 98 | } 99 | #region INTERACTIVE 100 | public void Pan(float horizontal, float vertical) { 101 | worldDirty = true; 102 | viewDirty = true; 103 | position.X += horizontal; 104 | position.Y += vertical; 105 | } 106 | public void Zoom(float value) { 107 | worldDirty = true; 108 | viewDirty = true; 109 | position.Z += value; 110 | } 111 | public void Pivot(float yaw, float pitch) { 112 | worldDirty = true; 113 | viewDirty = true; 114 | 115 | Matrix4 yawAngle = Matrix4.AngleAxis(yaw, up.X, up.Y, up.Z); 116 | forward = Matrix4.MultiplyVector(yawAngle, forward); 117 | 118 | Matrix4 pitchAngle = Matrix4.AngleAxis(pitch, right.X, right.Y, right.Z); 119 | forward = Matrix4.MultiplyVector(pitchAngle, forward); 120 | 121 | forward = Vector3.Normalize(forward); 122 | right = Vector3.Normalize(right); 123 | up = Vector3.Normalize(up); 124 | } 125 | #endregion 126 | 127 | #region FRUSTUM 128 | private static Plane FromNumbers(Vector4 numbers) { 129 | Vector3 abc = new Vector3(numbers.X, numbers.Y, numbers.Z); 130 | float mag = abc.Length(); 131 | abc.Normalize(); 132 | 133 | Plane p = new Plane(); 134 | p.Normal = abc; 135 | p.Distance = numbers.W / mag; 136 | return p; 137 | } 138 | 139 | public Plane[] Frustum { 140 | get { 141 | Plane[] frustum = new Plane[6]; 142 | 143 | Matrix4 vp = ProjectionMatrix * ViewMatrix; 144 | 145 | Vector4[] rows = new Vector4[4] {new Vector4(vp[0,0],vp[0,1],vp[0,2],vp[0,3]), 146 | new Vector4(vp[1,0],vp[1,1],vp[1,2],vp[1,3]), 147 | new Vector4(vp[2,0],vp[2,1],vp[2,2],vp[2,3]), 148 | new Vector4(vp[3,0],vp[3,1],vp[3,2],vp[3,3]), 149 | }; 150 | 151 | frustum[0] = FromNumbers(rows[3] + rows[0]); 152 | frustum[1] = FromNumbers(rows[3] - rows[0]); 153 | frustum[2] = FromNumbers(rows[3] + rows[1]); 154 | frustum[3] = FromNumbers(rows[3] - rows[1]); 155 | frustum[4] = FromNumbers(rows[3] + rows[2]); 156 | frustum[5] = FromNumbers(rows[3] - rows[2]); 157 | 158 | return frustum; 159 | //frustum[0] = left plane 160 | //frustum[1] = right plane 161 | //frustum[2] = bottom plane 162 | //frustum[3] = top plane 163 | //frustum[4] = near plane 164 | //frustum[5] = far plane 165 | } 166 | } 167 | #endregion 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/Math/Vector3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | 4 | namespace Math_Implementation { 5 | class Vector3 { 6 | public float X = 0; 7 | public float Y = 0; 8 | public float Z = 0; 9 | public float this[int i] { 10 | get { 11 | if (i == 0) { 12 | return X; 13 | } 14 | else if (i == 1) { 15 | return Y; 16 | } 17 | else if (i == 2) { 18 | return Z; 19 | } 20 | return 0; 21 | } 22 | set { 23 | if (i == 0) { 24 | X = value; ; 25 | } 26 | else if (i == 1) { 27 | Y = value; 28 | } 29 | else if (i == 2) { 30 | Z = value; 31 | } 32 | } 33 | } 34 | public Vector3() { 35 | X = Y = Z = 0.0f; 36 | } 37 | public Vector3(float x,float y,float z) { 38 | X = x; 39 | Y = y; 40 | Z = z; 41 | } 42 | public static Vector3 operator +(Vector3 vectorA, Vector3 vectorB) { 43 | return new Vector3(vectorA.X + vectorB.X, vectorA.Y + vectorB.Y, vectorA.Z + vectorB.Z); 44 | } 45 | public static Vector3 operator -(Vector3 vectorA, Vector3 vectorB) { 46 | return new Vector3(vectorA.X - vectorB.X, vectorA.Y - vectorB.Y, vectorA.Z - vectorB.Z); 47 | } 48 | public static Vector3 operator *(Vector3 vectorA, float scale) { 49 | return new Vector3(vectorA.X * scale, vectorA.Y * scale, vectorA.Z * scale); 50 | } 51 | public static Vector3 operator /(Vector3 vectorA,float scale) { 52 | return new Vector3(vectorA.X / scale, vectorA.Y / scale, vectorA.Z / scale); 53 | } 54 | public static Vector3 operator *(Vector3 vectorA,Vector3 vectorB) { 55 | return new Vector3(vectorA.X * vectorB.X, vectorA.Y * vectorB.Y, vectorA.Z * vectorB.Z); 56 | } 57 | public static Vector3 operator /(Vector3 vectorA,Vector3 vectorB) { 58 | return new Vector3(vectorA.X / vectorB.X, vectorA.Y / vectorB.Y, vectorA.Z / vectorB.Z); 59 | } 60 | public static float Dot(Vector3 vectorA,Vector3 vectorB) { 61 | float xComponent = vectorA.X * vectorB.X; 62 | float yComponent = vectorA.Y * vectorB.Y; 63 | float zComponent = vectorA.Z * vectorB.Z; 64 | return xComponent + yComponent + zComponent; 65 | } 66 | public float Dot(Vector3 vector) { 67 | float xComponent = this.X * vector.X; 68 | float yComponent = this.Y * vector.Y; 69 | float zComponent = this.Z * vector.Z; 70 | return xComponent + yComponent + zComponent; 71 | } 72 | public static float Length(Vector3 vectorA) { 73 | return (float)Math.Sqrt(Dot(vectorA, vectorA)); 74 | } 75 | public float Length() { 76 | return (float)Math.Sqrt(Dot(this, this)); 77 | } 78 | public static float LengthSquared(Vector3 vectorA) { 79 | return Dot(vectorA, vectorA); 80 | } 81 | public float LengthSquared() { 82 | return Dot(this, this); 83 | } 84 | public static Vector3 Normalize(Vector3 vectorA) { 85 | float length = Length(vectorA); 86 | float x = vectorA.X / length; 87 | float y = vectorA.Y / length; 88 | float z = vectorA.Z / length; 89 | return new Vector3(x, y, z); 90 | } 91 | public void Normalize() { 92 | float length = Length(this); 93 | X /= length; 94 | Y /= length; 95 | Z /= length; 96 | } 97 | public static float AngleBetween(Vector3 vectorA,Vector3 vectorB) { 98 | return (float)Math.Acos(Dot(Normalize(vectorA), Normalize(vectorB))); 99 | } 100 | public float AngleBetween(Vector3 vectorA) { 101 | return (float)Math.Acos(Dot(Normalize(this), Normalize(vectorA))); 102 | } 103 | public static Vector3 Projection(Vector3 vectorA,Vector3 vectorB) { 104 | float projectionLength = (Dot(vectorA, vectorB) / (Length(vectorB))); 105 | return Normalize(vectorB) * projectionLength; 106 | } 107 | public static Vector3 Perpendicular(Vector3 vectorA,Vector3 vectorB) { 108 | return (vectorB - Projection(vectorA, vectorB)); 109 | } 110 | public static Vector3 Cross(Vector3 vectorA,Vector3 vectorB) { 111 | Vector3 result = new Vector3(); 112 | result.X = (vectorA.Y * vectorB.Z) - (vectorA.Z * vectorB.Y); 113 | result.Y = (vectorA.Z * vectorB.X) - (vectorA.X * vectorB.Z); 114 | result.Z = (vectorA.X * vectorB.Y) - (vectorA.Y * vectorB.X); 115 | return result; 116 | } 117 | public void Cross(Vector3 vectorA) { 118 | X = (this.Y * vectorA.Z) - (this.Z * vectorA.Y); 119 | Y = (this.Z * vectorA.X) - (this.X * vectorA.Z); 120 | Z = (this.X * vectorA.Y) - (this.Y * vectorA.X); 121 | } 122 | public void Negate() { 123 | X *= -1.0f; 124 | Y *= -1.0f; 125 | Z *= -1.0f; 126 | } 127 | public static void Negate(Vector3 vectorA) { 128 | vectorA.X *= -1.0f; 129 | vectorA.Y *= -1.0f; 130 | vectorA.Z *= -1.0f; 131 | } 132 | public static bool Fequal(float a, float b) { 133 | return Math.Abs(a - b) < 0.0001; 134 | } 135 | public static bool operator ==(Vector3 vectorA, Vector3 vectorB) { 136 | return Fequal(vectorA.X, vectorB.X) && Fequal(vectorA.Y, vectorB.Y) && Fequal(vectorA.Z, vectorB.Z) ? true : false; 137 | } 138 | public static bool operator !=(Vector3 vectorA, Vector3 vectorB) { 139 | return !Fequal(vectorA.X, vectorB.X) || !Fequal(vectorA.Y,vectorB.Y) || !Fequal(vectorA.Z, vectorB.Z) ? true : false; 140 | } 141 | public static bool operator >=(Vector3 vectorA, Vector3 vectorB) { 142 | return vectorA.LengthSquared() >= vectorB.LengthSquared() ? true : false; 143 | } 144 | public static bool operator <=(Vector3 vectorA, Vector3 vectorB) { 145 | return vectorA.LengthSquared() <= vectorB.LengthSquared() ? true : false; 146 | } 147 | public static bool operator <(Vector3 vectorA, Vector3 vectorB) { 148 | return vectorA.LengthSquared() < vectorB.LengthSquared() ? true : false; 149 | } 150 | public static bool operator >(Vector3 vectorA, Vector3 vectorB) { 151 | return vectorA.LengthSquared() > vectorB.LengthSquared() ? true : false; 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/Samples/AABBSample.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using CollisionDetectionSelector.Primitive; 4 | 5 | namespace CollisionDetectionSelector.Samples { 6 | class AABBSample : Application { 7 | protected Vector3 cameraAngle = new Vector3(120.0f, -10f, 20.0f); 8 | protected float rads = (float)(System.Math.PI / 180.0f); 9 | 10 | AABB aabb1 = new AABB(); 11 | AABB aabb2 = new AABB(new Point(-3, -2, -3), new Point(-1, -1, -2)); 12 | AABB aabb3 = new AABB(new Point(5, 5, 5), new Vector3(2, 4, 3)); 13 | 14 | 15 | public override void Initialize(int width, int height) { 16 | // Seeing the back face of a square gives a better 17 | // overview of the actual geometry 18 | //GL.Enable(EnableCap.CullFace); 19 | GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); 20 | GL.PointSize(4f); 21 | 22 | System.Console.ResetColor(); 23 | CheckAABBMinMax(aabb1, 1, -1, -1, -1, 1, 1, 1); 24 | CheckAABBCenterExtents(aabb1, 1, 0, 0, 0, 1, 1, 1); 25 | System.Console.WriteLine("AABB1: " + aabb1); 26 | System.Console.WriteLine("\tCenter: " + aabb1.Center); 27 | System.Console.WriteLine("\tExtents: " + aabb1.Extents.X + ", " + aabb1.Extents.Y + ", " + aabb1.Extents.Z); 28 | 29 | System.Console.ResetColor(); 30 | CheckAABBMinMax(aabb2, 2, -3, -2, -3, -1, -1, -2); 31 | CheckAABBCenterExtents(aabb2, 2, -2, -1.5f, -2.5f, 1, 0.5f, 0.5f); 32 | System.Console.WriteLine("AABB2: " + aabb2); 33 | System.Console.WriteLine("\tCenter: " + aabb2.Center); 34 | System.Console.WriteLine("\tExtents: " + aabb2.Extents.X + ", " + aabb2.Extents.Y + ", " + aabb2.Extents.Z); 35 | 36 | System.Console.ResetColor(); 37 | CheckAABBMinMax(aabb3, 3, 3, 1, 2, 7, 9, 8); 38 | CheckAABBCenterExtents(aabb3, 3, 5, 5, 5, 2, 4, 3); 39 | System.Console.WriteLine("AABB3: " + aabb3); 40 | System.Console.WriteLine("\tCenter: " + aabb3.Center); 41 | System.Console.WriteLine("\tExtents: " + aabb3.Extents.X + ", " + aabb3.Extents.Y + ", " + aabb3.Extents.Z); 42 | } 43 | 44 | protected void CheckAABBCenterExtents(AABB aabb, int num, float cx, float cy, float cz, float ex, float ey, float ez) { 45 | if (aabb.Center.X != cx || aabb.Center.Y != cy || aabb.Center.Z != cz) { 46 | System.Console.ForegroundColor = System.ConsoleColor.Red; 47 | System.Console.WriteLine("AABB" + num + ", center is wrong"); 48 | System.Console.WriteLine("\tGot: (" + aabb.Center.X + ", " + aabb.Center.Y + ", " + aabb.Center.Z + ")"); 49 | System.Console.WriteLine("\tExpected: (" + cx + ", " + cy + ", " + cz + ")"); 50 | } 51 | 52 | if (aabb.Extents.X != ex || aabb.Extents.Y != ey || aabb.Extents.Z != ez) { 53 | System.Console.ForegroundColor = System.ConsoleColor.Red; 54 | System.Console.WriteLine("AABB" + num + ", extents is wrong"); 55 | System.Console.WriteLine("\tGot: (" + aabb.Extents.X + ", " + aabb.Extents.Y + ", " + aabb.Extents.Z + ")"); 56 | System.Console.WriteLine("\tExpected: (" + ex + ", " + ey + ", " + ez + ")"); 57 | } 58 | } 59 | 60 | protected void CheckAABBMinMax(AABB aabb, int num, float minX, float minY, float minz, float maxX, float maxY, float maxZ) { 61 | Point t = aabb.Min; 62 | if (t.X != minX || t.Y != minY || t.Z != minz) { 63 | System.Console.ForegroundColor = System.ConsoleColor.Red; 64 | System.Console.WriteLine("AABB" + num + ", min is wrong"); 65 | System.Console.WriteLine("\tGot: (" + t.X + ", " + t.Y + ", " + t.Z + ")"); 66 | System.Console.WriteLine("\tExpected: (" + minX + ", " + minY + ", " + minz + ")"); 67 | } 68 | t = aabb.Max; 69 | if (t.X != maxX || t.Y != maxY || t.Z != maxZ) { 70 | System.Console.ForegroundColor = System.ConsoleColor.Red; 71 | System.Console.WriteLine("AABB" + num + ", max is wrong"); 72 | System.Console.WriteLine("\tGot: (" + t.X + ", " + t.Y + ", " + t.Z + ")"); 73 | System.Console.WriteLine("\tExpected: (" + maxX + ", " + maxY + ", " + maxZ + ")"); 74 | } 75 | } 76 | 77 | public override void Render() { 78 | Vector3 eyePos = new Vector3(); 79 | eyePos.X = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 80 | eyePos.Y = cameraAngle.Z * -(float)System.Math.Sin(cameraAngle.Y * rads); 81 | eyePos.Z = -cameraAngle.Z * (float)System.Math.Cos(cameraAngle.X * rads * (float)System.Math.Cos(cameraAngle.Y * rads)); 82 | 83 | Matrix4 lookAt = Matrix4.LookAt(eyePos, new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f)); 84 | GL.LoadMatrix(Matrix4.Transpose(lookAt).Matrix); 85 | 86 | DrawAABBDebug(aabb1); 87 | DrawAABBDebug(aabb2); 88 | DrawAABBDebug(aabb3); 89 | } 90 | 91 | protected void DrawAABBDebug(AABB aabb) { 92 | GL.Color3(1f, 1f, 1f); 93 | aabb.Render(); 94 | GL.Color3(1f, 1f, 0f); 95 | aabb.Min.Render(); 96 | GL.Color3(1f, 0f, 1f); 97 | aabb.Max.Render(); 98 | GL.Begin(PrimitiveType.Lines); 99 | GL.Color3(1f, 0f, 0f); 100 | GL.Vertex3(aabb.Center.X, aabb.Center.Y, aabb.Center.Z); 101 | GL.Vertex3(aabb.Center.X + aabb.Extents.X, aabb.Center.Y, aabb.Center.Z); 102 | GL.Color3(0f, 1f, 0f); 103 | GL.Vertex3(aabb.Center.X, aabb.Center.Y, aabb.Center.Z); 104 | GL.Vertex3(aabb.Center.X, aabb.Center.Y + aabb.Extents.Y, aabb.Center.Z); 105 | GL.Color3(0f, 0f, 1f); 106 | GL.Vertex3(aabb.Center.X, aabb.Center.Y, aabb.Center.Z); 107 | GL.Vertex3(aabb.Center.X, aabb.Center.Y, aabb.Center.Z + aabb.Extents.Z); 108 | GL.End(); 109 | GL.Color3(0f, 1f, 1f); 110 | aabb.Center.Render(); 111 | } 112 | 113 | public override void Update(float deltaTime) { 114 | cameraAngle.X += 45.0f * deltaTime; 115 | } 116 | 117 | public override void Resize(int width, int height) { 118 | GL.Viewport(0, 0, width, height); 119 | GL.MatrixMode(MatrixMode.Projection); 120 | float aspect = (float)width / (float)height; 121 | Matrix4 perspective = Matrix4.Perspective(60, aspect, 0.01f, 1000.0f); 122 | GL.LoadMatrix(Matrix4.Transpose(perspective).Matrix); 123 | GL.MatrixMode(MatrixMode.Modelview); 124 | GL.LoadIdentity(); 125 | } 126 | } 127 | } -------------------------------------------------------------------------------- /CollisionDetectionSelector/Primitive/OBJ.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Graphics.OpenGL; 2 | using Math_Implementation; 3 | using System.Collections.Generic; 4 | 5 | namespace CollisionDetectionSelector.Primitive { 6 | class OBJ { 7 | 8 | #region Node 9 | public OBJ Parent = null; 10 | public List Children = new List(); 11 | #endregion 12 | 13 | OBJLoader model = null; 14 | 15 | //expose model bvhRoot 16 | public BVHNode BVHRoot { 17 | get { 18 | return model.BvhRoot; 19 | } 20 | } 21 | //end 22 | public bool IsEmpty { 23 | get { 24 | return model == null; 25 | } 26 | } 27 | 28 | protected Vector3 position = new Vector3(0.0f, 0.0f, 0.0f); 29 | protected Vector3 rotation = new Vector3(0.0f, 0.0f, 0.0f); 30 | protected Vector3 scale = new Vector3(1.0f, 1.0f, 1.0f); 31 | 32 | protected Matrix4 worldMatrix; 33 | protected bool wasRendered = false; 34 | protected bool dirtySelf = true;//true by default 35 | protected bool dirty { 36 | get { 37 | return dirtySelf; 38 | } 39 | set { 40 | bool contanier = value; 41 | dirtySelf = contanier; 42 | 43 | System.Diagnostics.Debug.Assert(dirtySelf == value); 44 | if (dirtySelf) { 45 | foreach (OBJ child in Children) { 46 | child.dirty = true; 47 | } 48 | } 49 | } 50 | } 51 | 52 | #region WorldSpace 53 | public Matrix4 WorldMatrix { 54 | get { 55 | if (dirty) { 56 | Matrix4 translation = Matrix4.Translate(position); 57 | 58 | Matrix4 pitch = Matrix4.XRotation(rotation.X); 59 | Matrix4 yaw = Matrix4.YRotation(rotation.Y); 60 | Matrix4 roll = Matrix4.ZRotation(rotation.Z); 61 | Matrix4 orientation = roll * pitch * yaw; 62 | 63 | Matrix4 scaling = Matrix4.Scale(scale); 64 | worldMatrix = translation * orientation * scaling; 65 | 66 | if (Parent != null) { 67 | worldMatrix = Parent.WorldMatrix* worldMatrix ; 68 | } 69 | 70 | dirty = false; 71 | } 72 | return worldMatrix; 73 | } 74 | } 75 | #endregion 76 | 77 | #region LocalSpace 78 | public Vector3 Position { 79 | get { return position; } 80 | set { 81 | position = value; 82 | dirty = true; 83 | } 84 | } 85 | 86 | public Vector3 Rotation { 87 | get { return rotation; } 88 | set { 89 | rotation = value; 90 | dirty = true; 91 | } 92 | } 93 | 94 | public Vector3 Scale { 95 | get { return scale; } 96 | set { 97 | scale = value; 98 | dirty = true; 99 | } 100 | } 101 | #endregion 102 | 103 | public AABB BoundingBox { 104 | get { 105 | return model.BoundingBox; 106 | } 107 | } 108 | public Sphere BoundingSphere { 109 | get { 110 | return model.BoundingSphere; 111 | } 112 | } 113 | public Triangle[] Mesh { 114 | get { 115 | return model.CollisionMesh; 116 | } 117 | } 118 | public OBJ(OBJLoader loader) { 119 | model = loader; 120 | } 121 | 122 | private int ChildrenRender(bool normal,bool bvh, bool debug) { 123 | int result = 0; 124 | if (Children != null) { 125 | foreach(OBJ child in Children) { 126 | if (normal) { 127 | result += child.Render(); 128 | } 129 | else if (bvh) { 130 | child.RenderBVH(); 131 | } 132 | else if (debug) { 133 | child.DebugRender(); 134 | } 135 | if(child.Children != null) { 136 | result += child.ChildrenRender(normal, bvh, debug); 137 | } 138 | } 139 | } 140 | return result; 141 | } 142 | public int Render() { 143 | int result = 0; 144 | 145 | GL.PushMatrix(); 146 | //always getter 147 | GL.MultMatrix(WorldMatrix.OpenGL); 148 | if (model != null) { 149 | model.Render(); 150 | result++; 151 | } 152 | GL.PopMatrix(); 153 | 154 | result += ChildrenRender(true, false, false); 155 | return result; 156 | } 157 | 158 | public void DebugRender() { 159 | GL.PushMatrix(); 160 | GL.MultMatrix(WorldMatrix.OpenGL); 161 | if (model != null) { 162 | model.DebugRender(); 163 | } 164 | GL.PopMatrix(); 165 | ChildrenRender(false, false, true); 166 | } 167 | 168 | #region BVH 169 | public void RenderBVH() { 170 | GL.PushMatrix(); 171 | GL.MultMatrix(WorldMatrix.OpenGL); 172 | if (model != null) { 173 | model.RenderBVH(); 174 | } 175 | GL.PopMatrix(); 176 | ChildrenRender(false, true, false); 177 | } 178 | #endregion 179 | 180 | public override string ToString() { 181 | return "Triangle count: " + model.NumCollisionTriangles; 182 | } 183 | public void ResetRenderFlag() { 184 | wasRendered = false; 185 | } 186 | public bool NonRecursiveRender(Plane[] frustum) { 187 | if (model == null || wasRendered) { 188 | return false; 189 | } 190 | Sphere bounds = new Sphere(); 191 | bounds.Position = new Point(Matrix4.MultiplyPoint(WorldMatrix, model.BoundingSphere.vPosition)); 192 | float scalar = System.Math.Abs(System.Math.Max(System.Math.Max( 193 | System.Math.Abs(WorldMatrix[0, 0]), System.Math.Abs(WorldMatrix[1, 1])), 194 | System.Math.Abs(WorldMatrix[2, 2]))); 195 | bounds.Radius = model.BoundingSphere.Radius * scalar; 196 | if (!Collisions.Intersects(frustum, bounds)) { 197 | return false; 198 | } 199 | 200 | wasRendered = true; 201 | GL.PushMatrix(); 202 | GL.MultMatrix(WorldMatrix.OpenGL); 203 | model.Render(); 204 | GL.PopMatrix(); 205 | return true; 206 | } 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /CollisionDetectionSelector/Math/Vector2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | 4 | namespace Math_Implementation { 5 | public class Vector2 { 6 | public float X = 0.0f; 7 | public float Y = 0.0f; 8 | public float this[int i] { 9 | get { 10 | if (i == 0) { 11 | return X; 12 | } 13 | else if (i == 1) { 14 | return Y; 15 | } 16 | return 0; 17 | } 18 | set { 19 | if (i == 0) { 20 | X = value; 21 | } 22 | else if (i == 1) { 23 | Y = value; 24 | } 25 | } 26 | } 27 | public Vector2(float _x, float _y) { 28 | X = _x; 29 | Y = _y; 30 | } 31 | public Vector2() { 32 | X = 0; 33 | Y = 0; 34 | } 35 | public static Vector2 operator +(Vector2 vector1, Vector2 vector2) { 36 | return new Vector2(vector1.X + vector2.X, vector1.Y + vector2.Y); 37 | } 38 | public static Vector2 Add (Vector2 vector1, Vector2 vector2) { 39 | return new Vector2(vector1.X + vector2.X, vector1.Y + vector2.Y); 40 | } 41 | public void Add(Vector2 vector) { 42 | X += vector.X; 43 | Y += vector.Y; 44 | } 45 | public static Vector2 operator -(Vector2 vector1, Vector2 vector2) { 46 | Vector2 result = new Vector2(vector1.X - vector2.X, vector1.Y - vector2.Y); 47 | return result; 48 | } 49 | public static Vector2 Subtract(Vector2 vector1, Vector2 vector2) { 50 | Vector2 result = new Vector2(vector1.X - vector2.X, vector1.Y - vector2.Y); 51 | return result; 52 | } 53 | public void Subtract(Vector2 vector) { 54 | X -= vector.X; 55 | Y -= vector.Y; 56 | } 57 | public static Vector2 operator *(Vector2 vector, float scale) { 58 | Vector2 result = new Vector2(vector.X * scale, vector.Y * scale); 59 | return result; 60 | } 61 | public static Vector2 ScalarMultiply(Vector2 vector, float scale) { 62 | Vector2 result = new Vector2(vector.X * scale, vector.Y * scale); 63 | return result; 64 | } 65 | public void ScalarMultiply(float scale) { 66 | X *= scale; 67 | Y *= scale; 68 | } 69 | public static Vector2 operator *(Vector2 vector1, Vector2 vector2) { 70 | Vector2 result = new Vector2(vector1.X * vector2.X, vector1.Y * vector2.Y); 71 | return result; 72 | } 73 | public static Vector2 ScalarMultiply (Vector2 vector1, Vector2 vector2) { 74 | Vector2 result = new Vector2(vector1.X * vector2.X, vector1.Y * vector2.Y); 75 | return result; 76 | } 77 | public void ScalarMultiply(Vector2 scale) { 78 | X *= scale.X; 79 | Y *= scale.Y; 80 | } 81 | public static Vector2 operator /(Vector2 vector, float scale) { 82 | Vector2 result = new Vector2(vector.X / scale, vector.Y / scale); 83 | return result; 84 | } 85 | public static Vector2 operator /(Vector2 vector1, Vector2 vector2) { 86 | Vector2 result = new Vector2(vector1.X / vector2.X, vector1.Y / vector2.Y); 87 | return result; 88 | } 89 | public static Vector2 ScalarDivide (Vector2 vector, float scale) { 90 | Vector2 result = new Vector2(vector.X / scale, vector.Y / scale); 91 | return result; 92 | } 93 | public static Vector2 ScalarDivide(Vector2 vector1, Vector2 vector2) { 94 | Vector2 result = new Vector2(vector1.X / vector2.X, vector1.Y / vector2.Y); 95 | return result; 96 | } 97 | public void ScalarDivide(float scale) { 98 | X /= scale; 99 | Y /= scale; 100 | } 101 | public void ScalarDivide(Vector2 scale) { 102 | X /= scale.X; 103 | Y /= scale.Y; 104 | } 105 | public static float Dot(Vector2 vector1, Vector2 vector2) { 106 | float xComponent = vector1.X * vector2.X; 107 | float yComponent = vector1.Y * vector2.Y; 108 | return xComponent + yComponent; 109 | } 110 | public float Dot(Vector2 vector) { 111 | float xComponent = X * vector.X; 112 | float yComponent = Y * vector.Y; 113 | return xComponent + yComponent; 114 | } 115 | public static float Length(Vector2 vector) { 116 | return (float)Math.Sqrt((double)Dot(vector, vector)); 117 | } 118 | public float Length() { 119 | return (float)Math.Sqrt((double)Dot(this, this)); 120 | } 121 | public float LengthSquared() { 122 | return Dot(this, this); 123 | } 124 | public static float LengthSquared(Vector2 vector) { 125 | return Dot(vector, vector); 126 | } 127 | public static Vector2 Normalize(Vector2 vector) { 128 | float length = Length(vector); 129 | vector.X /= length; 130 | vector.Y /= length; 131 | return new Vector2(vector.X, vector.Y); 132 | } 133 | public void Normalize() { 134 | X /= Length(); 135 | Y /= Length(); 136 | } 137 | public float AngleBetween(Vector2 vector) { 138 | return (float)Math.Acos((double)Dot(Normalize(this), Normalize(vector))); 139 | } 140 | public static float AngleBetween(Vector2 vector1, Vector2 vector2) { 141 | return (float)Math.Acos((double)Dot(Normalize(vector1), Normalize(vector2))); 142 | } 143 | public static Vector2 operator -(Vector2 vector) { 144 | return new Vector2(vector.X * -1.0f, vector.Y * -1.0f); 145 | } 146 | public void Negate() { 147 | X *= -1.0f; 148 | Y *= -1.0f; 149 | } 150 | public static void Negate(Vector2 vector) { 151 | vector.X *= -1.0f; 152 | vector.Y *= -1.0f; 153 | } 154 | private static bool Fequal(float a, float b) { 155 | return Math.Abs(a - b) < 0.00001; 156 | } 157 | public static bool operator ==(Vector2 vector1,Vector2 vector2) { 158 | return Fequal(vector1.X,vector2.X) && Fequal(vector1.Y,vector2.Y) ? true : false; 159 | } 160 | public static bool operator !=(Vector2 vector1, Vector2 vector2) { 161 | return !Fequal(vector1.X, vector2.X) || !Fequal(vector1.Y, vector2.Y) ? true : false; 162 | } 163 | public static bool operator >=(Vector2 vector1, Vector2 vector2) { 164 | return vector1.LengthSquared() >= vector2.LengthSquared() ? true : false; 165 | } 166 | public static bool operator <=(Vector2 vector1, Vector2 vector2) { 167 | return vector1.LengthSquared() <= vector2.LengthSquared() ? true : false; 168 | } 169 | public static bool operator <(Vector2 vector1, Vector2 vector2) { 170 | return vector1.LengthSquared() < vector2.LengthSquared() ? true : false; 171 | } 172 | public static bool operator >(Vector2 vector1, Vector2 vector2) { 173 | return vector1.LengthSquared() > vector2.LengthSquared() ? true : false; 174 | } 175 | } 176 | } 177 | --------------------------------------------------------------------------------