CollidingElement.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. using fun.Basics.Shapes;
  2. using fun.Core;
  3. using OpenTK;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using Environment = fun.Core.Environment;
  8. namespace fun.Basics
  9. {
  10. public sealed class CollidingElement : Element
  11. {
  12. private static float GAP = 0.1f;
  13. private Vector3 lastPos;
  14. private Vector3 currPos;
  15. private TransformElement transform;
  16. private List<ICollider> colliders;
  17. public CollidingElement(Environment environment, Entity entity)
  18. : base(environment, entity)
  19. {
  20. transform = entity.GetElement<TransformElement>() as TransformElement;
  21. currPos = transform.Position;
  22. lastPos = transform.Position;
  23. }
  24. public override void Initialize()
  25. {
  26. colliders = new List<ICollider>(environment.Entities
  27. .Where(e => e.ContainsElement<ICollider>())
  28. .Select(e => e.GetElement<ICollider>() as ICollider));
  29. }
  30. public override void Update(double time)
  31. {
  32. ICollider colliding = null;
  33. do
  34. {
  35. lastPos = currPos;
  36. currPos = transform.Position;
  37. var move = currPos - lastPos;
  38. var ray = new Ray(lastPos, Vector3.Normalize(move));
  39. colliding = colliders.FirstOrDefault(c =>
  40. {
  41. var distance = c.Intersects(ray);
  42. return distance.HasValue && move.LengthSquared > (distance.Value * distance.Value);
  43. });
  44. if (colliding != null)
  45. {
  46. // Rays in alle Richtungen initializieren
  47. var xyz = new
  48. {
  49. XP = new Ray(lastPos, Vector3.UnitX),
  50. YP = new Ray(lastPos, Vector3.UnitY),
  51. ZP = new Ray(lastPos, Vector3.UnitZ),
  52. XM = new Ray(lastPos, -Vector3.UnitX),
  53. YM = new Ray(lastPos, -Vector3.UnitY),
  54. ZM = new Ray(lastPos, -Vector3.UnitZ)
  55. };
  56. // Distances festlegen, falls es welche gibt
  57. var distance = new
  58. {
  59. X = colliding.Intersects(move.X > 0 ? xyz.XP : xyz.XM),
  60. Y = colliding.Intersects(move.Y > 0 ? xyz.YP : xyz.YM),
  61. Z = colliding.Intersects(move.Z > 0 ? xyz.ZP : xyz.ZM)
  62. };
  63. // Collisionen prüfen
  64. var isColliding = new
  65. {
  66. X = distance.X.HasValue && Math.Abs(move.X) > distance.X.Value,
  67. Y = distance.Y.HasValue && Math.Abs(move.Y) > distance.Y.Value,
  68. Z = distance.Z.HasValue && Math.Abs(move.Z) > distance.Z.Value
  69. };
  70. float reduction;
  71. //Collision verhindern
  72. if (isColliding.X)
  73. {
  74. reduction = distance.X.Value / Math.Abs(move.X);
  75. move.X *= reduction - GAP;
  76. }
  77. else if (isColliding.Y)
  78. {
  79. reduction = distance.Y.Value / Math.Abs(move.Y);
  80. move.Y *= reduction - GAP;
  81. }
  82. else if (isColliding.Z)
  83. {
  84. reduction = distance.Z.Value / Math.Abs(move.Z);
  85. move.Z *= reduction - GAP;
  86. }
  87. transform.Position = currPos = lastPos + move;
  88. }
  89. } while (colliding != null);
  90. }
  91. #region old code
  92. //if (false)//colliding != null)
  93. //{
  94. // XRAY.Position = lastPos;
  95. // YRAY.Position = lastPos;
  96. // ZRAY.Position = lastPos;
  97. // XRAM.Position = lastPos;
  98. // YRAM.Position = lastPos;
  99. // ZRAM.Position = lastPos;
  100. // var Xdistance = colliding.Intersects(move.X > 0 ? XRAY : XRAM);
  101. // var Ydistance = colliding.Intersects(move.Y > 0 ? YRAY : YRAM);
  102. // var Zdistance = colliding.Intersects(move.Z > 0 ? ZRAY : ZRAM);
  103. // var Xcolliding = Xdistance.HasValue && Math.Abs(move.X) > Xdistance.Value;
  104. // var Ycolliding = Ydistance.HasValue && Math.Abs(move.Y) > Ydistance.Value;
  105. // var Zcolliding = Zdistance.HasValue && Math.Abs(move.Z) > Zdistance.Value;
  106. // float reduction;
  107. // if (Xcolliding)
  108. // {
  109. // reduction = Xdistance.Value / Math.Abs(move.X);
  110. // move.X *= reduction - GAP;
  111. // }
  112. // else if (Ycolliding)
  113. // {
  114. // reduction = Ydistance.Value / Math.Abs(move.Y);
  115. // move.Y *= reduction - GAP;
  116. // }
  117. // else if (Zcolliding)
  118. // {
  119. // reduction = Zdistance.Value / Math.Abs(move.Z);
  120. // move.Z *= reduction - GAP;
  121. // }
  122. // transform.Position = currPos = lastPos + move;
  123. // XRAY.Position = Vector3.Zero;
  124. // YRAY.Position = Vector3.Zero;
  125. // ZRAY.Position = Vector3.Zero;
  126. //}
  127. //if (colliding != null)
  128. //{
  129. // var distance = colliding.Intersects(ray).Value;
  130. // var reduction = distance / move.Length();
  131. // move *= reduction - (reduction / 10);
  132. // transform.Position = currPos = lastPos + move;
  133. //}
  134. #endregion
  135. }
  136. }