💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

222 lines
5.8 KiB

  1. /*
  2. * Copyright (C) 2017 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper Source Code.
  5. *
  6. * Antkeeper Source Code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper Source Code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "agent.hpp"
  20. Agent::Agent():
  21. navmeshTriangle(nullptr),
  22. barycentricPosition(0.0f),
  23. position(0.0f),
  24. forward(0, 0, -1),
  25. up(0, 1, 0),
  26. right(1, 0, 0),
  27. rotation(1, 0, 0, 0)
  28. //wanderDirection(0, 0, -1),
  29. //velocity(0.0f)
  30. {}
  31. /*
  32. void Agent::applyForce(const Vector3& force)
  33. {
  34. acceleration += force;
  35. }
  36. void Agent::updateVelocity()
  37. {
  38. // Limit acceleration
  39. acceleration = limit(acceleration / mass, maxAcceleration);
  40. // Add acceleration to velocity and limit
  41. velocity = limit(velocity + acceleration, maxSpeed);
  42. // Reset acceleration to zero
  43. acceleration = Vector3(0.0f);
  44. }
  45. Vector3 Agent::wander(float dt)
  46. {
  47. // Calculate center of wander circle
  48. Vector3 wanderCircleCenter = position + forward * wanderCircleDistance;
  49. // Calculate wander force
  50. Vector3 target = wanderCircleCenter + wanderDirection * wanderCircleRadius;
  51. // Rotate wander direction by a random displacement angle
  52. float displacement = frand(-wanderRate * 0.5f, wanderRate * 0.5f);
  53. wanderDirection = glm::normalize(glm::angleAxis(displacement, up) * wanderDirection);
  54. return seek(target);
  55. }
  56. Vector3 Agent::seek(const Vector3& target) const
  57. {
  58. Vector3 desiredVelocity = glm::normalize(target - position) * maxSpeed;
  59. return desiredVelocity - velocity;
  60. }
  61. Vector3 Agent::flee(const Vector3& target) const
  62. {
  63. Vector3 desiredVelocity = glm::normalize(position - target) * maxSpeed;
  64. return desiredVelocity - velocity;
  65. }
  66. Vector3 Agent::containment(const Vector3& probe) const
  67. {
  68. std::vector<Navmesh::Step> traversal;
  69. Navmesh::traverse(navmeshTriangle, barycentricPosition, probe, &traversal);
  70. if (traversal.empty())
  71. {
  72. return Vector3(0.0f);
  73. }
  74. const Navmesh::Step& step = traversal.back();
  75. // If not on edge or on connected edge
  76. if (step.edge == nullptr || step.edge->symmetric != nullptr)
  77. {
  78. return Vector3(0.0f);
  79. }
  80. // Calculate difference between probe position and position on edge
  81. //Vector3 end = cartesian(step.end,
  82. // step.triangle->edge->vertex->position,
  83. // step.triangle->edge->next->vertex->position,
  84. // step.triangle->edge->previous->vertex->position);
  85. //Vector3 difference = probe - end;
  86. //float depth = 0.0f;
  87. //if (nonzero(difference))
  88. //{
  89. // depth = glm::length(difference);
  90. //}
  91. // Calculate edge normal
  92. const Vector3& a = step.edge->vertex->position;
  93. const Vector3& b = step.edge->next->vertex->position;
  94. Vector3 ab = glm::normalize(b - a);
  95. Vector3 edgeNormal = glm::cross(up, ab);
  96. // Calculate reflection vector of forward vector and edge normal
  97. //Vector3 reflection = glm::reflect(forward, edgeNormal);
  98. //Vector3 target = cartesian(step.end,
  99. // step.triangle->edge->vertex->position,
  100. // step.triangle->edge->next->vertex->position,
  101. // step.triangle->edge->previous->vertex->position) + reflection * 0.1f;
  102. //std::cout << "reflection: " << reflection.x << ", " << reflection.y << ", " << reflection.z << std::endl;
  103. return edgeNormal;
  104. }
  105. Vector3 Agent::separation(const std::list<Agent*>& neighbors) const
  106. {
  107. Vector3 force(0.0f);
  108. for (Agent* neighbor: neighbors)
  109. {
  110. Vector3 difference = position - neighbor->position;
  111. float distanceSquared = glm::dot(difference, difference);
  112. if (distanceSquared > 0.0f && distanceSquared < separationRadiusSquared)
  113. {
  114. force += difference * (1.0f / distanceSquared);
  115. }
  116. }
  117. if (nonzero(force))
  118. {
  119. force = glm::normalize(force);
  120. }
  121. return force;
  122. }
  123. */
  124. void Agent::setPosition(Navmesh::Triangle* triangle, const Vector3& position)
  125. {
  126. // Update navmesh triangle and position
  127. navmeshTriangle = triangle;
  128. barycentricPosition = position;
  129. // Convert navmesh-space barycentric position to world-space cartesian position
  130. const Vector3& a = triangle->edge->vertex->position;
  131. const Vector3& b = triangle->edge->next->vertex->position;
  132. const Vector3& c = triangle->edge->previous->vertex->position;
  133. this->position = cartesian(position, a, b, c);
  134. }
  135. void Agent::setOrientation(const Vector3& newForward, const Vector3& newUp)
  136. {
  137. // Calculate alignment quaternion
  138. Quaternion alignment = glm::rotation(up, newUp);
  139. // Rebuild vector basis
  140. forward = newForward;
  141. right = glm::normalize(glm::cross(newUp, forward));
  142. up = glm::cross(forward, right);
  143. // Calculate rotation quaternion from vector basis
  144. rotation = glm::normalize(glm::quat_cast(Matrix3(right, up, forward)));
  145. // Align wander direction
  146. //wanderDirection = glm::normalize(project_on_plane(alignment * wanderDirection, Vector3(0.0f), up));
  147. }
  148. /*
  149. void Agent::setMaxSpeed(float speed)
  150. {
  151. maxSpeed = speed;
  152. }
  153. void Agent::setVelocity(const Vector3& velocity)
  154. {
  155. this->velocity = velocity;
  156. }
  157. void Agent::setWanderCircleDistance(float distance)
  158. {
  159. wanderCircleDistance = distance;
  160. }
  161. void Agent::setWanderCircleRadius(float radius)
  162. {
  163. wanderCircleRadius = radius;
  164. }
  165. void Agent::setWanderRate(float angle)
  166. {
  167. wanderRate = angle;
  168. }
  169. void Agent::setSeparationRadius(float radius)
  170. {
  171. separationRadius = radius;
  172. separationRadiusSquared = separationRadius * separationRadius;
  173. }
  174. */
  175. /** EXAMPLE USAGE
  176. Vector3 wanderForce = wander(dt) * wanderWeight;
  177. Vector3 fleeForce = flee(mouse) * fleeWeight;
  178. Vector3 steerForce = wanderForce + fleeForce;
  179. steer(steerForce);
  180. **/