Merge pull request #93 from teamfisk/OctreeRaycasting
Entity in octree hit by ray
This commit is contained in:
@@ -20,6 +20,9 @@
|
||||
class World;
|
||||
struct ComponentWrapper;
|
||||
|
||||
template<typename T>
|
||||
class Octree;
|
||||
|
||||
namespace Collision
|
||||
{
|
||||
//Return true if the ray hits the box.
|
||||
@@ -44,21 +47,24 @@ bool RayVsTriangle(const Ray& ray,
|
||||
float& outVCoord,
|
||||
bool trueOnNegativeDistance = false);
|
||||
//Return true if the ray hits any of the triangles in the model. Stops checking when a hit is detected.
|
||||
bool RayVsModel(const Ray& ray,
|
||||
const std::vector<RawModel::Vertex>& modelVertices,
|
||||
const std::vector<unsigned int>& modelIndices);
|
||||
bool RayVsModel(const Ray& ray,
|
||||
const RawModel::Vertex* modelVertices,
|
||||
const std::vector<unsigned int>& modelIndices,
|
||||
const glm::mat4& modelMatrix);
|
||||
//Return true if the ray hits any of the triangles in the model.
|
||||
//Also returns the position of the intersection point. Will loop through all the whole model indices.
|
||||
bool RayVsModel(const Ray& ray,
|
||||
const std::vector<RawModel::Vertex>& modelVertices,
|
||||
const RawModel::Vertex* modelVertices,
|
||||
const std::vector<unsigned int>& modelIndices,
|
||||
const glm::mat4& modelMatrix,
|
||||
glm::vec3& outHitPosition);
|
||||
//Return true if the ray hits any of the triangles in the model.
|
||||
//Also returns the distance from the ray origin to the closest
|
||||
//intersection point, and the barycentric u,v-coordinates. Will loop through all the whole model indices.
|
||||
bool RayVsModel(const Ray& ray,
|
||||
const std::vector<RawModel::Vertex>& modelVertices,
|
||||
const RawModel::Vertex* modelVertices,
|
||||
const std::vector<unsigned int>& modelIndices,
|
||||
const glm::mat4& modelMatrix,
|
||||
float& outDistance,
|
||||
float& outUCoord,
|
||||
float& outVCoord);
|
||||
@@ -81,6 +87,13 @@ bool AABBVsAABB(const AABB& a, const AABB& b, glm::vec3& minimumTranslation);
|
||||
// Calculates an absolute AABB from an entity AABB component
|
||||
boost::optional<EntityAABB> EntityAbsoluteAABB(EntityWrapper& entity, bool takeModelBox = false);
|
||||
boost::optional<EntityAABB> AbsoluteAABBExplosionEffect(EntityWrapper& entity);
|
||||
//Returns the first entity hit by the input ray. entitiesPotentiallyHitSorted needs to be sorted
|
||||
//by their distance to the ray, e.g. result from Octree<EntityAABB>::ObjectsPossiblyHitByRay.
|
||||
//Returns boost::none if none was hit. outDistance will be the distance to the intersection point if the ray intersects.
|
||||
boost::optional<EntityAABB> EntityFirstHitByRay(const Ray& ray, std::vector<EntityAABB> entitiesPotentiallyHitSorted, float outDistance, glm::vec3& outIntersectPos);
|
||||
//Returns the first entity hit by the input ray that exists in the octree.
|
||||
//outDistance will be the distance to the intersection point if the ray intersects.
|
||||
boost::optional<EntityAABB> EntityFirstHitByRay(const Ray& ray, Octree<EntityAABB>* octree, float outDistance, glm::vec3& outIntersectPos);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@ public:
|
||||
void ObjectsInSameRegion(const Box& box, std::vector<T>& outObjects);
|
||||
//Get the objects that are inside the frustum, the objects are put in outObjects.
|
||||
void ObjectsInFrustum(const Frustum& frustum, std::vector<T>& outObjects);
|
||||
//Get objects, which AABB the input ray intersects, the objects are put in outObjects.
|
||||
void ObjectsPossiblyHitByRay(const Ray& ray, std::vector<T>& outObjects);
|
||||
//Empty the tree of all objects, static and dynamic.
|
||||
void ClearObjects();
|
||||
//Empty the tree of all dynamic objects. Static objects remain in the tree.
|
||||
@@ -100,6 +102,8 @@ struct Child
|
||||
void ObjectsInSameRegion(const Box& box, std::vector<T>& outObjects) const;
|
||||
template<typename T>
|
||||
void ObjectsInFrustum(const Frustum& frustum, std::vector<T>& outObjects, bool takeAllDontTest) const;
|
||||
template<typename T>
|
||||
void ObjectsPossiblyHitByRay(const Ray& ray, std::vector<T>& outObjects) const;
|
||||
void ClearObjects();
|
||||
void ClearDynamicObjects();
|
||||
bool RayCollides(const Ray& ray, Output& data) const;
|
||||
@@ -119,6 +123,15 @@ struct Child
|
||||
std::vector<int> childIndicesContainingBox(const AABB& box) const;
|
||||
};
|
||||
|
||||
//To be able to sort child nodes and contained objects based on distance to ray origin.
|
||||
struct RaySorterInfo
|
||||
{
|
||||
int Index;
|
||||
float Distance;
|
||||
};
|
||||
|
||||
bool isFirstLower(const RaySorterInfo& first, const RaySorterInfo& second);
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -164,6 +177,13 @@ void Octree<T>::ObjectsInFrustum(const Frustum& frustum, std::vector<T>& outObje
|
||||
m_Root->ObjectsInFrustum(frustum, outObjects, false);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Octree<T>::ObjectsPossiblyHitByRay(const Ray& ray, std::vector<T>& outObjects)
|
||||
{
|
||||
falsifyObjectChecks();
|
||||
m_Root->ObjectsPossiblyHitByRay(ray, outObjects);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Octree<T>::ClearObjects()
|
||||
{
|
||||
@@ -282,4 +302,59 @@ void OctSpace::Child::ObjectsInFrustum(const Frustum& frustum, std::vector<T>& o
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void OctSpace::Child::ObjectsPossiblyHitByRay(const Ray& ray, std::vector<T>& outObjects) const
|
||||
{
|
||||
//If the node AABB is missed, everything it contains is missed.
|
||||
if (Collision::RayAABBIntr(ray, m_Box)) {
|
||||
//If the ray shoots the tree, and it is a parent.
|
||||
if (hasChildren()) {
|
||||
//Sort children according to their distance from the ray origin.
|
||||
std::vector<RaySorterInfo> childInfos;
|
||||
childInfos.resize(8);
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
childInfos[i] = { i, glm::distance(ray.Origin(), m_Children[i]->m_Box.Origin()) };
|
||||
}
|
||||
std::sort(childInfos.begin(), childInfos.end(), isFirstLower);
|
||||
//Loop through the children, starting with the one closest to the ray origin. I.e the first to be hit.
|
||||
for (const RaySorterInfo& info : childInfos) {
|
||||
m_Children[info.Index]->ObjectsPossiblyHitByRay(ray, outObjects);
|
||||
}
|
||||
} else {
|
||||
//Check against boxes in the node.
|
||||
bool intersected = false;
|
||||
float dist;
|
||||
//Sort all contained objects according to the distance from the ray origin to
|
||||
//the intersection, if they are intersecting.
|
||||
std::vector<RaySorterInfo> objectHitInfos;
|
||||
objectHitInfos.reserve(m_StaticObjIndices.size() + m_DynamicObjIndices.size());
|
||||
for (int i : m_StaticObjIndices) {
|
||||
//If we haven't tested against this object before, and the ray hits.
|
||||
if (!m_StaticObjectsRef[i].Checked &&
|
||||
Collision::RayVsAABB(ray, *m_StaticObjectsRef[i].Box, dist)) {
|
||||
objectHitInfos.push_back({ i, dist });
|
||||
}
|
||||
m_StaticObjectsRef[i].Checked = true;
|
||||
}
|
||||
for (int i : m_DynamicObjIndices) {
|
||||
//If we haven't tested against this object before, and the ray hits.
|
||||
if (!m_DynamicObjectsRef[i].Checked &&
|
||||
Collision::RayVsAABB(ray, *m_DynamicObjectsRef[i].Box, dist)) {
|
||||
objectHitInfos.push_back({ i + (int)m_StaticObjIndices.size(), dist });
|
||||
}
|
||||
m_DynamicObjectsRef[i].Checked = true;
|
||||
}
|
||||
std::sort(objectHitInfos.begin(), objectHitInfos.end(), isFirstLower);
|
||||
int startSize = (int)outObjects.size();
|
||||
outObjects.resize(startSize + objectHitInfos.size());
|
||||
for (int i = 0; i < objectHitInfos.size(); ++i) {
|
||||
outObjects[startSize + i] = (objectHitInfos[i].Index < m_StaticObjIndices.size()) ?
|
||||
*static_cast<T*>(m_StaticObjectsRef[objectHitInfos[i].Index].Box.get()) :
|
||||
*static_cast<T*>(m_DynamicObjectsRef[objectHitInfos[i].Index - m_StaticObjIndices.size()].Box.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user