载入中...
搜索中...
未找到
BoidsCommon.h
浏览该文件的文档.
1#pragma once
2
5
6#include <glm/glm.hpp>
7
8#include <algorithm>
9#include <cmath>
10#include <span>
11
13
15inline float compactWeight(float dist, float radius) {
16 if (radius <= 1e-6f || dist >= radius) return 0.f;
17 const float q = dist / radius;
18 const float t = 1.f - q;
19 return t * t;
20}
21
23inline bool isInFieldOfView(const glm::vec3& forward, const glm::vec3& toNeighbor, float fovDegrees) {
24 if (fovDegrees >= 359.f) return true;
25 const float len = glm::length(toNeighbor);
26 if (len < 1e-6f) return true;
27 const float cosHalf = std::cos(0.5f * glm::radians(fovDegrees));
29 return glm::dot(glm::normalize(forward), toNeighbor / len) >= cosHalf;
30}
31
34 glm::vec3 separation{0.f};
35 glm::vec3 cohesionPos{0.f};
36 glm::vec3 alignmentVel{0.f};
37 float sepWeightSum = 0.f;
38 float cohWeightSum = 0.f;
39 float aliWeightSum = 0.f;
40 int samples = 0;
41};
42
46inline NeighborAccum gatherNeighbors(std::span<const AgentState> agents, int selfIndex, const glm::vec3& forward,
47 float sepR, float cohR, float aliR, float fovDeg, int maxSamples) {
48 NeighborAccum acc;
49 const glm::vec3 selfPos = agents[static_cast<size_t>(selfIndex)].position;
50 const float maxR = std::max({sepR, cohR, aliR});
51 for (int j = 0; j < static_cast<int>(agents.size()) && acc.samples < maxSamples; ++j) {
52 if (j == selfIndex || agents[static_cast<size_t>(j)].alive == 0) continue;
53 const glm::vec3 delta = agents[static_cast<size_t>(j)].position - selfPos;
54 const float dist = glm::length(delta);
55 if (dist > maxR || dist < 1e-5f) continue;
56 if (!isInFieldOfView(forward, delta, fovDeg)) continue;
57
58 if (const float w = compactWeight(dist, sepR); w > 0.f) {
59 acc.separation -= (delta / dist) * w;
60 acc.sepWeightSum += w;
61 }
62 if (const float w = compactWeight(dist, cohR); w > 0.f) {
63 acc.cohesionPos += agents[static_cast<size_t>(j)].position * w;
64 acc.cohWeightSum += w;
65 }
66 if (const float w = compactWeight(dist, aliR); w > 0.f) {
67 acc.alignmentVel += agents[static_cast<size_t>(j)].velocity * w;
68 acc.aliWeightSum += w;
69 }
70 ++acc.samples;
71 }
72 return acc;
73}
74
76inline glm::vec3 markerForce(const glm::vec3& pos, const std::vector<EnvironmentMarker>& markers, bool attract) {
78 glm::vec3 f(0.f);
79 for (const auto& m : markers) {
80 const glm::vec3 d = m.position - pos;
81 const float dist = glm::length(d);
82 if (dist < 1e-4f || dist > m.radius) continue;
83 const float w = compactWeight(dist, m.radius) * m.strength;
84 f += (attract ? 1.f : -1.f) * (d / dist) * w;
85 }
86 return f;
87}
88
90inline void integrateBoid(AgentState& out, const AgentState& in, glm::vec3 accel, float dt, float maxAccel,
91 float maxSpeed, float maxHTurn, float maxVTurn) {
92 const float aLen = glm::length(accel);
93 if (aLen > maxAccel && aLen > 1e-6f) accel *= maxAccel / aLen;
94
95 glm::vec3 vel = in.velocity + accel * dt;
96 const float speed = glm::length(vel);
97 if (speed > maxSpeed && speed > 1e-6f) vel *= maxSpeed / speed;
98
99 // Horizontal / vertical turn limiting relative to previous heading.
100 glm::vec3 prevDir = in.velocity;
101 if (glm::length(prevDir) < 1e-4f) prevDir = glm::vec3(0.f, 0.f, 1.f);
102 prevDir = glm::normalize(prevDir);
103 glm::vec3 newDir = vel;
104 if (glm::length(newDir) < 1e-4f) newDir = prevDir;
105 else
106 newDir = glm::normalize(newDir);
107
108 glm::vec3 prevH = glm::normalize(glm::vec3(prevDir.x, 0.f, prevDir.z) + glm::vec3(1e-5f, 0.f, 0.f));
109 glm::vec3 newH = glm::normalize(glm::vec3(newDir.x, 0.f, newDir.z) + glm::vec3(1e-5f, 0.f, 0.f));
110 float hAng = std::acos(std::clamp(glm::dot(prevH, newH), -1.f, 1.f));
111 const float maxH = maxHTurn * dt;
112 if (hAng > maxH && hAng > 1e-5f) {
113 const float t = maxH / hAng;
114 newH = glm::normalize(glm::mix(prevH, newH, t));
115 }
116 float prevPitch = std::asin(std::clamp(prevDir.y, -1.f, 1.f));
117 float newPitch = std::asin(std::clamp(newDir.y, -1.f, 1.f));
118 const float maxV = maxVTurn * dt;
119 newPitch = prevPitch + std::clamp(newPitch - prevPitch, -maxV, maxV);
120 newDir = glm::normalize(glm::vec3(newH.x * std::cos(newPitch), std::sin(newPitch), newH.z * std::cos(newPitch)));
121
122 const float outSpeed = std::min(glm::length(vel), maxSpeed);
123 out = in;
124 out.velocity = newDir * outSpeed;
125 out.position = in.position + out.velocity * dt;
126 out.rotation = lookRotation(out.velocity);
127 out.age = in.age + dt;
128 out.alive = in.alive;
129}
130
131} // namespace eve::gpuagents::detail
float w
Definition AnimClip.cpp:738
std::array< double, 10 > q
std::vector< Marker > markers
std::array< float, 3 > position
float f
float radius
float d
float t
float m[16]
float compactWeight(float dist, float radius)
Compact-support radial weight w(q)=(1-q)^2 for q in [0,1).
Definition BoidsCommon.h:15
bool isInFieldOfView(const glm::vec3 &forward, const glm::vec3 &toNeighbor, float fovDegrees)
True when neighbor direction is inside a forward cone (degrees).
Definition BoidsCommon.h:23
glm::vec3 markerForce(const glm::vec3 &pos, const std::vector< EnvironmentMarker > &markers, bool attract)
Marker force.
Definition BoidsCommon.h:76
void integrateBoid(AgentState &out, const AgentState &in, glm::vec3 accel, float dt, float maxAccel, float maxSpeed, float maxHTurn, float maxVTurn)
Clamp acceleration then integrate semi-implicit Euler with turn-rate limits.
Definition BoidsCommon.h:90
NeighborAccum gatherNeighbors(std::span< const AgentState > agents, int selfIndex, const glm::vec3 &forward, float sepR, float cohR, float aliR, float fovDeg, int maxSamples)
Gather neighborhood forces with compact weights and FOV / sample caps.
Definition BoidsCommon.h:46
glm::quat lookRotation(const glm::vec3 &forward, const glm::vec3 &upHint=glm::vec3(0.f, 1.f, 0.f))
Builds a facing quaternion from a unit forward and approximate up.
Definition AgentState.h:36
Standardized per-agent simulation output shared by all effect kinds.
Definition AgentState.h:12
glm::quat rotation
wxyz storage (glm default).
Definition AgentState.h:15
std::uint32_t alive
0 = recycled / inactive slot.
Definition AgentState.h:18
NeighborAccum public API.
Definition BoidsCommon.h:33