public void Paint(PaintEventArgs e) { for (int i = 0; i < Spheres.Count - 1; i++) { for (int j = i + 1; j < Spheres.Count; j++) { Sphere3d s1 = Spheres[i]; Sphere3d s2 = Spheres[j]; float? t = CollisionSystem.CalculateCollision(s1, s2); if (t.HasValue && t.Value != 0) { s1.Move(t.Value, ref c1); //collp.X = s1.Direction.X * t.Value + s1.Position.X; //collp.Y = s1.Direction.Y * t.Value + s1.Position.Y; e.Graphics.DrawCircle(Pens.Red, c1.Position.X, c1.Position.Y, s1.Radius); s2.Move(t.Value, ref c2); //collp.X = s2.Direction.X * t.Value + s2.Position.X; //collp.Y = s2.Direction.Y * t.Value + s2.Position.Y; e.Graphics.DrawCircle(Pens.Red, c2.Position.X, c2.Position.Y, s2.Radius); e.Graphics.DrawLine(CollisionCirecleCentersPen, c1.Position.X, c1.Position.Y, c2.Position.X, c2.Position.Y); CollisionSystem.CalculateReaction(0, c1, c2); float tx = c1.Position.X + c1.Direction.X; float ty = c1.Position.Y + c1.Direction.Y; e.Graphics.DrawLine(Pens.Black, c1.Position.X, c1.Position.Y, tx, ty); } } } }
public virtual void Move(float t, ref Sphere3d s) { s.Position.X = Position.X + Direction.X * t; s.Position.Y = Position.Y + Direction.Y * t; s.Position.Z = Position.Z + Direction.Z * t; s.Direction.X = Direction.X; s.Direction.Y = Direction.Y; s.Direction.Z = Direction.Z; }
private static void WriteDebugInfo(float rotationY, Sphere3d s1, Sphere3d s2) { string vector(Vector3d v) { return($"new Vector3d({v.X}f, {v.Y}f, {v.Z}f)"); } Console.WriteLine($"float rotationY = {rotationY}f;"); Console.WriteLine($"Sphere3d s1 = new Sphere3d({vector(s1.Position)}, {s1.Radius}, {vector(s1.Direction)});"); Console.WriteLine($"Sphere3d s2 = new Sphere3d({vector(s2.Position)}, {s1.Radius}, {vector(s2.Direction)});"); }
public void Paint(PaintEventArgs e, Pen pen, Sphere3d sphere) { float doubleRadius = sphere.Radius * 2; float sx = (sphere.Position.X + TranslateX) * Scale; float sz = (sphere.Position.Z + TranslateZ) * Scale; e.Graphics.DrawCircle(pen, sx, sz, sphere.Radius * Scale); e.Graphics.DrawArrow(pen, sx, sz, sx + sphere.Direction.X * Scale, sz + sphere.Direction.Z * Scale); if (Reaction != null) { e.Graphics.DrawArrow(Pens.Red, sx, sz, sx + Reaction.X * Scale, sz + Reaction.Z * Scale); } }
public PathfinderScene(int sphereCount, int width, int height, Random random) { Obstacles = new List <Sphere3d>(); for (int i = 0; i < sphereCount; i++) { Obstacles.Add(RandomSphere(random, width, height, dynamic: false)); } Checkpoint = RandomNonCollidingSphere(random, width, height, Obstacles, dynamic: false); Vehicle = new Sphere3dVehicle(RandomNonCollidingSphere(random, width, height, Obstacles, dynamic: true)); List <Sphere3d> allSpheres = new List <Sphere3d>(); allSpheres.AddRange(Obstacles); allSpheres.Add(Checkpoint); allSpheres.Add(Vehicle.Sphere); CollisionSystem = new CollisionSystem(allSpheres, new Triangle[] { }); }
public Race(int numberOfSpheres) { Spheres = new List <Sphere3d>(); PlayerSphere = new Sphere3d(new Vector3d(), 0.2f, new Vector3d()); Speed = 0.1f; RotationY = 45; Input = new RaceInputModel(); Random random = new Random(); Spheres.Add(PlayerSphere); for (int i = 0; i < numberOfSpheres; i++) { float x = random.Next(100); float z = random.Next(100) - 50; float r = (float)random.NextDouble() * 2.0f + 0.2f; Spheres.Add(new Sphere3d(new Vector3d(x, 0, z), r, new Vector3d())); } Ground = new Triangle(new Vector3d(-100, -5, -50), new Vector3d(0, -5, 50), new Vector3d(100, -5, -50)); collisionSystem = new CollisionSystem(Spheres, new Triangle[] { Ground }); }
public static float?CalculateCollision(Sphere3d s1, Sphere3d s2) { return(null); //Vector3d.Sub(s1.Position, s2.Position, ref vecs); //Vector3d.Sub(s1.Direction, s2.Direction, ref vecv); //float radiusSum = s1.Radius + s2.Radius; //float c = vecs.Dot(vecs) - radiusSum * radiusSum; //float t = 0; // //if (c < 0) //{ // return 0; //} //else //{ // float a = vecv.Dot(vecv); // float b = vecv.Dot(vecs); // // if (b >= 0) // { // return null; // } // else // { // float d = b * b - a * c; // // if (d < 0) // { // return null; // } // else // { // t = (float)(-b - Math.Sqrt(d)) / a; // return t; // } // } //} }
public static float?CalculateCollision(Sphere3d s1, Sphere3d s2) { Vector3d.Sub(s1.Position, s2.Position, ref vecs); Vector3d.Sub(s1.Direction, s2.Direction, ref vecv); float radiusSum = s1.Radius + s2.Radius; float c = vecs.Dot(vecs) - radiusSum * radiusSum; float t = 0; if (c < 0) { return(0); } else { float a = vecv.Dot(vecv); float b = vecv.Dot(vecs); if (b >= 0) { return(null); } else { float d = b * b - a * c; if (d < 0) { return(null); } else { t = (float)(-b - Math.Sqrt(d)) / a; return(t); } } } }
public bool IsColliding(Sphere3d s) { double d = Position.Distance(s.Position); return(d < Radius + s.Radius); }
public void Set(Sphere3d s) { Position.Set(s.Position); Direction.Set(s.Direction); Radius = s.Radius; }
public PaintableSphere3d(Sphere3d sphere, Brush brush) { Sphere = sphere; Brush = brush; }
public PaintableSphere3d(Sphere3d sphere, Pen pen) { Sphere = sphere; Pen = pen; }
public Sphere3dVehicle(Sphere3d sphere) { Sphere = sphere; }
public float?Update(float rotationY, float t) { float? result = null; HashSet <int> toRecalculate = new HashSet <int>(); if (t >= closestTime) { Console.WriteLine("Collision"); MoveObjects(closestTime); Sphere3d s1 = Objects[closest.X]; Sphere3d s2 = Objects[closest.Y]; result = CalculateReaction(rotationY, s1, s2); SubstractCollisionTimes(closestTime); toRecalculate.Add(closest.X); toRecalculate.Add(closest.Y); } else { MoveObjects(t); SubstractCollisionTimes(t); closestTime -= t; } for (int i = 0; i < Objects.Count; i++) { Sphere3d sphere = Objects[i]; if (sphere.Position.X < 0 && sphere.Direction.X < 0) { sphere.Direction.X = -sphere.Direction.X; toRecalculate.Add(i); } if (sphere.Position.X > 800 && sphere.Direction.X > 0) { sphere.Direction.X = -sphere.Direction.X; toRecalculate.Add(i); } if (sphere.Position.Y < 0 && sphere.Direction.Y < 0) { sphere.Direction.Y = -sphere.Direction.Y; toRecalculate.Add(i); } if (sphere.Position.Y > 600 && sphere.Direction.Y > 0) { sphere.Direction.Y = -sphere.Direction.Y; toRecalculate.Add(i); } } foreach (int i in toRecalculate) { RecalculateCollisions(i); } if (toRecalculate.Count > 0) { RecalculateClosestCollision(); } return(result); }
public static float?CalculateReaction(float rotationY, Sphere3d s1, Sphere3d s2) { float? result = null; Vector3d n = s1.Position - s2.Position; n.Normalize(); n.Mul(n.Dot(s1.Direction) * 2); Vector3d r = s1.Direction - n; if (s2 != null) { //Vector3d direction = new Vector3d(); //direction.Set(s1.Direction); //direction.Normalize(); result = 57.29577f * (float)Math.Atan2(r.Z, r.X); CollisionForm.RotationY = rotationY; CollisionForm.NewRotationY = result.Value; CollisionForm.Sphere1 = s1; CollisionForm.Sphere2 = s2; CollisionForm.Reaction = r; CollisionForm.Empty = false; CollisionForm.Refresh(); } s1.Direction = r; return(result); // https://math.stackexchange.com/questions/13261/how-to-get-a-reflection-vector //s1.Direction = r; //float rx = //float x = s1.Direction.X; //float y = s1.Direction.Y; //s1.Direction.X = 0; //s1.Direction.Y = 0; //s2.Direction.X = x; //s2.Direction.Y = y; ////s2.RotationY = s1.RotationY; ////s2.RecalculateDirection(5); //s2.RotationY = s1.RotationY; ////s1.RotationY += 180; //Vector3d vecx = new Vector3d(); //Vector3d.Sub(s1.Position, s2.Position, ref vecx); //Vector3d.Normalize(vecx, ref vecx); //Vector3d vecv1 = new Vector3d(s1.Direction); //float x1 = vecx.Dot(s1.Direction); //Vector3d vecv1x = new Vector3d(vecx); //vecv1x.Mul(x1); //Vector3d vecv1y = new Vector3d(); //Vector3d.Sub(vecv1, vecv1x, ref vecv1y); //float m1 = 1; // //vecx.Mul(-1); //Vector3d vecv2 = new Vector3d(s2.Direction); //float x2 = vecx.Dot(s2.Direction); //Vector3d vecv2x = new Vector3d(vecx); //vecv2x.Mul(x2); //Vector3d vecv2y = new Vector3d(); //Vector3d.Sub(vecv2, vecv2x, ref vecv2y); //float m2 = 1; // //Vector3d vecv2xa = new Vector3d(vecv2x); //vecv2xa.Mul((2 * m2) / (m1 + m2)); //vecv1x.Mul((m1 - m2) / (m1 - m2)); //Vector3d.Sum(ref s1.Direction, vecv1x, vecv2xa, vecv1); }