-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNSquared.cpp
136 lines (116 loc) · 2.59 KB
/
NSquared.cpp
1
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include "stdafx.h"
#include <list>
#include "Object.h"
#include "NSquared.h"
#include "AABB.h"
std::list<std::pair<Object*, Object*>> &NSquared::ComputePairs()
{
m_pairs.clear();
//outer loop
auto end = m_aabbs.end();
for (auto i = m_aabbs.begin(); i != end; ++i)
{
//***************************************
//TODO: NEED A WAY TO UPDATE AABBS AS THEY
//CURRENTLY DON'T UPDATE THEIR POSITION AND
//SO THEY WON'T BE DETECTED WHEN COLLIDING
//***************************************
//inner loop
auto jStart = i;
for (auto j = ++jStart; j != end; ++j)
{
AABB *aabbA = *i;
AABB *aabbB = *j;
Object *objectA = aabbA->object;
Object *objectB = aabbB->object;
aabbA = aabbA->object->aabb;
aabbB = aabbB->object->aabb;
//skip same body collision
if (objectA == objectB)
continue;
//add object pair
if (aabbA->overlaps(*aabbB))
{
m_pairs.push_back(std::make_pair(aabbA->object, aabbB->object));
}
}
}
return m_pairs;
}
Object *NSquared::Pick(const sf::Vector2f &point) const
{
for (auto &aabb : m_aabbs)
{
if (aabb->containsPoint(point))
{
return aabb->object;
}
}
//no collider found
return nullptr;
}
void NSquared::Query(const AABB &aabb, std::vector<Object*> &out) const
{
for (auto &objectAABB : m_aabbs)
{
if (objectAABB->overlaps(aabb))
{
out.push_back(objectAABB->object);
}
}
}
RayCastResult NSquared::RayCast(const Ray2 &ray) const
{
//test AABBs for candidates
std::vector<Object*> candidateList;
candidateList.reserve(m_aabbs.size());
for (AABB *aabb : m_aabbs)
{
/*if (aabb->TestRay(ray))
{
candidateList.push_back(aabb->object);
}*/
}
//struct for storing ray-collider test results
struct ResultEntry
{
Object *object;
float t;
sf::Vector2f normal;
bool operator<(const ResultEntry &rhs) const
{
//smaller t = closer
return t > rhs.t;
}
};
//test actual objects
std::vector<ResultEntry> resultList;
resultList.reserve(candidateList.size());
for (Object *object : candidateList)
{
//hit point = ray.pos + t * ray.dir
float t;
sf::Vector2f normal;
/*if (object->TestRay(ray, t, normal))
{
ResultEntry entry = {object, t, normal };
resultList.push_back(entry);
}*/
}
//sort the result list
std::sort(resultList.begin(), resultList.end());
RayCastResult result;
if (!resultList.empty())
{
//the first result entry is the closest one
ResultEntry &entry = resultList.front();
result.hit = true;
result.object = entry.object;
result.normal = entry.normal;
result.position = ray.pos + entry.t * ray.dir;
}
else {
result.hit = false;
}
return result;
}