mirror of
https://github.com/lubosz/overte.git
synced 2025-04-24 14:03:17 +02:00
Some untested ray intersection bits.
This commit is contained in:
parent
7fc55e5596
commit
802cc3eeed
4 changed files with 175 additions and 5 deletions
|
@ -10,6 +10,8 @@
|
|||
#include <QScriptEngine>
|
||||
#include <QtDebug>
|
||||
|
||||
#include <GeometryUtil.h>
|
||||
|
||||
#include "MetavoxelData.h"
|
||||
#include "MetavoxelUtil.h"
|
||||
#include "ScriptCache.h"
|
||||
|
@ -821,6 +823,65 @@ int SpannerVisitor::visit(MetavoxelInfo& info) {
|
|||
return info.isLeaf ? STOP_RECURSION : DEFAULT_ORDER;
|
||||
}
|
||||
|
||||
RayIntersectionVisitor::RayIntersectionVisitor(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const QVector<AttributePointer>& inputs, const QVector<AttributePointer>& outputs, const MetavoxelLOD& lod) :
|
||||
MetavoxelVisitor(inputs, outputs, lod),
|
||||
_origin(origin),
|
||||
_direction(direction),
|
||||
_order(encodeOrder(direction)) {
|
||||
}
|
||||
|
||||
int RayIntersectionVisitor::visit(MetavoxelInfo& info) {
|
||||
float distance;
|
||||
if (!info.getBounds().findRayIntersection(_origin, _direction, distance)) {
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
return visit(info, distance);
|
||||
}
|
||||
|
||||
RayIntersectionSpannerVisitor::RayIntersectionSpannerVisitor(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const QVector<AttributePointer>& spannerInputs, const QVector<AttributePointer>& inputs,
|
||||
const QVector<AttributePointer>& outputs, const MetavoxelLOD& lod) :
|
||||
RayIntersectionVisitor(origin, direction, inputs + spannerInputs, outputs, lod),
|
||||
_spannerInputCount(spannerInputs.size()) {
|
||||
}
|
||||
|
||||
void RayIntersectionSpannerVisitor::prepare() {
|
||||
Spanner::incrementVisit();
|
||||
}
|
||||
|
||||
class SpannerDistance {
|
||||
public:
|
||||
Spanner* spanner;
|
||||
float distance;
|
||||
};
|
||||
|
||||
bool operator<(const SpannerDistance& first, const SpannerDistance& second) {
|
||||
return first.distance < second.distance;
|
||||
}
|
||||
|
||||
int RayIntersectionSpannerVisitor::visit(MetavoxelInfo& info, float distance) {
|
||||
QVarLengthArray<SpannerDistance, 4> spannerDistances;
|
||||
for (int i = _inputs.size() - _spannerInputCount; i < _inputs.size(); i++) {
|
||||
foreach (const SharedObjectPointer& object, info.inputValues.at(i).getInlineValue<SharedObjectSet>()) {
|
||||
Spanner* spanner = static_cast<Spanner*>(object.data());
|
||||
if (spanner->testAndSetVisited()) {
|
||||
SpannerDistance spannerDistance = { spanner };
|
||||
if (spanner->findRayIntersection(_origin, _direction, spannerDistance.distance)) {
|
||||
spannerDistances.append(spannerDistance);
|
||||
}
|
||||
}
|
||||
}
|
||||
qStableSort(spannerDistances);
|
||||
foreach (const SpannerDistance& spannerDistance, spannerDistances) {
|
||||
if (!visit(spannerDistance.spanner, spannerDistance.distance)) {
|
||||
return SHORT_CIRCUIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
return info.isLeaf ? STOP_RECURSION : _order;
|
||||
}
|
||||
|
||||
DefaultMetavoxelGuide::DefaultMetavoxelGuide() {
|
||||
}
|
||||
|
||||
|
@ -1119,6 +1180,10 @@ SpannerRenderer* Spanner::getRenderer() {
|
|||
return _renderer;
|
||||
}
|
||||
|
||||
bool Spanner::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const {
|
||||
return _bounds.findRayIntersection(origin, direction, distance);
|
||||
}
|
||||
|
||||
QByteArray Spanner::getRendererClassName() const {
|
||||
return "SpannerRendererer";
|
||||
}
|
||||
|
@ -1212,6 +1277,10 @@ bool Sphere::getAttributeValues(MetavoxelInfo& info) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Sphere::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const {
|
||||
return findRaySphereIntersection(origin, direction, getTranslation(), getScale(), distance);
|
||||
}
|
||||
|
||||
QByteArray Sphere::getRendererClassName() const {
|
||||
return "SphereRenderer";
|
||||
}
|
||||
|
|
|
@ -191,7 +191,7 @@ public:
|
|||
glm::vec3 getCenter() const { return minimum + glm::vec3(size, size, size) * 0.5f; }
|
||||
};
|
||||
|
||||
/// Interface for visitors to metavoxels.
|
||||
/// Base class for visitors to metavoxels.
|
||||
class MetavoxelVisitor {
|
||||
public:
|
||||
|
||||
|
@ -241,9 +241,7 @@ protected:
|
|||
MetavoxelLOD _lod;
|
||||
};
|
||||
|
||||
typedef QSharedPointer<MetavoxelVisitor> MetavoxelVisitorPointer;
|
||||
|
||||
/// Interface for visitors to spanners.
|
||||
/// Base class for visitors to spanners.
|
||||
class SpannerVisitor : public MetavoxelVisitor {
|
||||
public:
|
||||
|
||||
|
@ -264,6 +262,49 @@ protected:
|
|||
int _spannerInputCount;
|
||||
};
|
||||
|
||||
/// Base class for ray intersection visitors.
|
||||
class RayIntersectionVisitor : public MetavoxelVisitor {
|
||||
public:
|
||||
|
||||
RayIntersectionVisitor(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const QVector<AttributePointer>& inputs,
|
||||
const QVector<AttributePointer>& outputs = QVector<AttributePointer>(),
|
||||
const MetavoxelLOD& lod = MetavoxelLOD());
|
||||
|
||||
/// Visits a metavoxel that the ray intersects.
|
||||
virtual int visit(MetavoxelInfo& info, float distance) = 0;
|
||||
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
|
||||
protected:
|
||||
|
||||
glm::vec3 _origin;
|
||||
glm::vec3 _direction;
|
||||
int _order;
|
||||
};
|
||||
|
||||
/// Base class for ray intersection spanner visitors.
|
||||
class RayIntersectionSpannerVisitor : public RayIntersectionVisitor {
|
||||
public:
|
||||
|
||||
RayIntersectionSpannerVisitor(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const QVector<AttributePointer>& spannerInputs,
|
||||
const QVector<AttributePointer>& inputs = QVector<AttributePointer>(),
|
||||
const QVector<AttributePointer>& outputs = QVector<AttributePointer>(),
|
||||
const MetavoxelLOD& lod = MetavoxelLOD());
|
||||
|
||||
/// Visits a spanner that the ray intersects.
|
||||
/// \return true to continue, false to short-circuit the tour
|
||||
virtual bool visit(Spanner* spanner, float distance) = 0;
|
||||
|
||||
virtual void prepare();
|
||||
virtual int visit(MetavoxelInfo& info, float distance);
|
||||
|
||||
protected:
|
||||
|
||||
int _spannerInputCount;
|
||||
};
|
||||
|
||||
/// Interface for objects that guide metavoxel visitors.
|
||||
class MetavoxelGuide : public SharedObject {
|
||||
Q_OBJECT
|
||||
|
@ -389,6 +430,9 @@ public:
|
|||
/// Returns a pointer to the renderer, creating it if necessary.
|
||||
SpannerRenderer* getRenderer();
|
||||
|
||||
/// Finds the intersection between the described ray and this spanner.
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||
|
||||
signals:
|
||||
|
||||
void boundsWillChange();
|
||||
|
@ -469,7 +513,8 @@ public:
|
|||
|
||||
virtual const QVector<AttributePointer>& getAttributes() const;
|
||||
virtual bool getAttributeValues(MetavoxelInfo& info) const;
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||
|
||||
signals:
|
||||
|
||||
void colorChanged(const QColor& color);
|
||||
|
|
|
@ -150,6 +150,12 @@ Box::Box(const glm::vec3& minimum, const glm::vec3& maximum) :
|
|||
minimum(minimum), maximum(maximum) {
|
||||
}
|
||||
|
||||
bool Box::contains(const glm::vec3& point) const {
|
||||
return point.x >= minimum.x && point.x <= maximum.x &&
|
||||
point.y >= minimum.y && point.y <= maximum.y &&
|
||||
point.z >= minimum.z && point.z <= maximum.z;
|
||||
}
|
||||
|
||||
bool Box::contains(const Box& other) const {
|
||||
return other.minimum.x >= minimum.x && other.maximum.x <= maximum.x &&
|
||||
other.minimum.y >= minimum.y && other.maximum.y <= maximum.y &&
|
||||
|
@ -173,6 +179,52 @@ glm::vec3 Box::getVertex(int index) const {
|
|||
(index & Z_MAXIMUM_FLAG) ? maximum.z : minimum.z);
|
||||
}
|
||||
|
||||
// finds the intersection between a ray and the facing plane on one axis
|
||||
static bool findIntersection(float origin, float direction, float minimum, float maximum, float& distance) {
|
||||
if (direction > EPSILON) {
|
||||
distance = (minimum - origin) / direction;
|
||||
return true;
|
||||
} else if (direction < -EPSILON) {
|
||||
distance = (maximum - origin) / direction;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// determines whether a value is within the extents
|
||||
static bool isWithin(float value, float minimum, float maximum) {
|
||||
return value >= minimum && value <= maximum;
|
||||
}
|
||||
|
||||
bool Box::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const {
|
||||
// handle the trivial case where the box contains the origin
|
||||
if (contains(origin)) {
|
||||
distance = 0.0f;
|
||||
return true;
|
||||
}
|
||||
// check each axis
|
||||
float axisDistance;
|
||||
if ((findIntersection(origin.x, direction.x, minimum.x, maximum.x, axisDistance) && axisDistance >= 0 &&
|
||||
isWithin(origin.y + axisDistance*direction.y, minimum.y, maximum.y) &&
|
||||
isWithin(origin.z + axisDistance*direction.z, minimum.z, maximum.z))) {
|
||||
distance = axisDistance;
|
||||
return true;
|
||||
}
|
||||
if ((findIntersection(origin.y, direction.y, minimum.y, maximum.y, axisDistance) && axisDistance >= 0 &&
|
||||
isWithin(origin.x + axisDistance*direction.x, minimum.x, maximum.x) &&
|
||||
isWithin(origin.z + axisDistance*direction.z, minimum.z, maximum.z))) {
|
||||
distance = axisDistance;
|
||||
return true;
|
||||
}
|
||||
if ((findIntersection(origin.z, direction.z, minimum.z, maximum.z, axisDistance) && axisDistance >= 0 &&
|
||||
isWithin(origin.y + axisDistance*direction.y, minimum.y, maximum.y) &&
|
||||
isWithin(origin.x + axisDistance*direction.x, minimum.x, maximum.x))) {
|
||||
distance = axisDistance;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Box operator*(const glm::mat4& matrix, const Box& box) {
|
||||
// start with the constant component
|
||||
Box newBox(glm::vec3(matrix[3][0], matrix[3][1], matrix[3][2]), glm::vec3(matrix[3][0], matrix[3][1], matrix[3][2]));
|
||||
|
|
|
@ -41,6 +41,8 @@ public:
|
|||
|
||||
Box(const glm::vec3& minimum = glm::vec3(), const glm::vec3& maximum = glm::vec3());
|
||||
|
||||
bool contains(const glm::vec3& point) const;
|
||||
|
||||
bool contains(const Box& other) const;
|
||||
|
||||
bool intersects(const Box& other) const;
|
||||
|
@ -50,6 +52,8 @@ public:
|
|||
glm::vec3 getVertex(int index) const;
|
||||
|
||||
glm::vec3 getCenter() const { return (minimum + maximum) * 0.5f; }
|
||||
|
||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||
};
|
||||
|
||||
DECLARE_STREAMABLE_METATYPE(Box)
|
||||
|
|
Loading…
Reference in a new issue