mirror of
https://github.com/lubosz/overte.git
synced 2025-08-07 17:01:06 +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 <QScriptEngine>
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
|
|
||||||
|
#include <GeometryUtil.h>
|
||||||
|
|
||||||
#include "MetavoxelData.h"
|
#include "MetavoxelData.h"
|
||||||
#include "MetavoxelUtil.h"
|
#include "MetavoxelUtil.h"
|
||||||
#include "ScriptCache.h"
|
#include "ScriptCache.h"
|
||||||
|
@ -821,6 +823,65 @@ int SpannerVisitor::visit(MetavoxelInfo& info) {
|
||||||
return info.isLeaf ? STOP_RECURSION : DEFAULT_ORDER;
|
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() {
|
DefaultMetavoxelGuide::DefaultMetavoxelGuide() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1119,6 +1180,10 @@ SpannerRenderer* Spanner::getRenderer() {
|
||||||
return _renderer;
|
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 {
|
QByteArray Spanner::getRendererClassName() const {
|
||||||
return "SpannerRendererer";
|
return "SpannerRendererer";
|
||||||
}
|
}
|
||||||
|
@ -1212,6 +1277,10 @@ bool Sphere::getAttributeValues(MetavoxelInfo& info) const {
|
||||||
return true;
|
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 {
|
QByteArray Sphere::getRendererClassName() const {
|
||||||
return "SphereRenderer";
|
return "SphereRenderer";
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,7 +191,7 @@ public:
|
||||||
glm::vec3 getCenter() const { return minimum + glm::vec3(size, size, size) * 0.5f; }
|
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 {
|
class MetavoxelVisitor {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -241,9 +241,7 @@ protected:
|
||||||
MetavoxelLOD _lod;
|
MetavoxelLOD _lod;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef QSharedPointer<MetavoxelVisitor> MetavoxelVisitorPointer;
|
/// Base class for visitors to spanners.
|
||||||
|
|
||||||
/// Interface for visitors to spanners.
|
|
||||||
class SpannerVisitor : public MetavoxelVisitor {
|
class SpannerVisitor : public MetavoxelVisitor {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -264,6 +262,49 @@ protected:
|
||||||
int _spannerInputCount;
|
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.
|
/// Interface for objects that guide metavoxel visitors.
|
||||||
class MetavoxelGuide : public SharedObject {
|
class MetavoxelGuide : public SharedObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -389,6 +430,9 @@ public:
|
||||||
/// Returns a pointer to the renderer, creating it if necessary.
|
/// Returns a pointer to the renderer, creating it if necessary.
|
||||||
SpannerRenderer* getRenderer();
|
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:
|
signals:
|
||||||
|
|
||||||
void boundsWillChange();
|
void boundsWillChange();
|
||||||
|
@ -469,7 +513,8 @@ public:
|
||||||
|
|
||||||
virtual const QVector<AttributePointer>& getAttributes() const;
|
virtual const QVector<AttributePointer>& getAttributes() const;
|
||||||
virtual bool getAttributeValues(MetavoxelInfo& info) const;
|
virtual bool getAttributeValues(MetavoxelInfo& info) const;
|
||||||
|
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void colorChanged(const QColor& color);
|
void colorChanged(const QColor& color);
|
||||||
|
|
|
@ -150,6 +150,12 @@ Box::Box(const glm::vec3& minimum, const glm::vec3& maximum) :
|
||||||
minimum(minimum), maximum(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 {
|
bool Box::contains(const Box& other) const {
|
||||||
return other.minimum.x >= minimum.x && other.maximum.x <= maximum.x &&
|
return other.minimum.x >= minimum.x && other.maximum.x <= maximum.x &&
|
||||||
other.minimum.y >= minimum.y && other.maximum.y <= maximum.y &&
|
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);
|
(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) {
|
Box operator*(const glm::mat4& matrix, const Box& box) {
|
||||||
// start with the constant component
|
// 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]));
|
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());
|
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 contains(const Box& other) const;
|
||||||
|
|
||||||
bool intersects(const Box& other) const;
|
bool intersects(const Box& other) const;
|
||||||
|
@ -50,6 +52,8 @@ public:
|
||||||
glm::vec3 getVertex(int index) const;
|
glm::vec3 getVertex(int index) const;
|
||||||
|
|
||||||
glm::vec3 getCenter() const { return (minimum + maximum) * 0.5f; }
|
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)
|
DECLARE_STREAMABLE_METATYPE(Box)
|
||||||
|
|
Loading…
Reference in a new issue