mirror of
https://github.com/overte-org/overte.git
synced 2025-04-23 10:53:34 +02:00
Ordered visitation bits.
This commit is contained in:
parent
c4f29005a0
commit
60b0281095
5 changed files with 162 additions and 63 deletions
interface/src
libraries/metavoxels/src
|
@ -61,13 +61,14 @@ void MetavoxelSystem::simulate(float deltaTime) {
|
|||
// simulate the clients
|
||||
_points.clear();
|
||||
_simulateVisitor.setDeltaTime(deltaTime);
|
||||
_simulateVisitor.setOrder(-Application::getInstance()->getViewFrustum()->getDirection());
|
||||
foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
|
||||
if (node->getType() == NodeType::MetavoxelServer) {
|
||||
QMutexLocker locker(&node->getMutex());
|
||||
MetavoxelClient* client = static_cast<MetavoxelClient*>(node->getLinkedData());
|
||||
if (client) {
|
||||
client->simulate(deltaTime);
|
||||
client->getData().guide(_simulateVisitor);
|
||||
client->guide(_simulateVisitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +110,7 @@ void MetavoxelSystem::render() {
|
|||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
|
||||
|
||||
|
||||
glDrawArrays(GL_POINTS, 0, _points.size());
|
||||
|
||||
glDisable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
|
||||
|
@ -127,7 +128,7 @@ void MetavoxelSystem::render() {
|
|||
QMutexLocker locker(&node->getMutex());
|
||||
MetavoxelClient* client = static_cast<MetavoxelClient*>(node->getLinkedData());
|
||||
if (client) {
|
||||
client->getData().guide(_renderVisitor);
|
||||
client->guide(_renderVisitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -147,15 +148,16 @@ MetavoxelSystem::SimulateVisitor::SimulateVisitor(QVector<Point>& points) :
|
|||
_points(points) {
|
||||
}
|
||||
|
||||
void MetavoxelSystem::SimulateVisitor::visit(Spanner* spanner) {
|
||||
bool MetavoxelSystem::SimulateVisitor::visit(Spanner* spanner) {
|
||||
spanner->getRenderer()->simulate(_deltaTime);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MetavoxelSystem::SimulateVisitor::visit(MetavoxelInfo& info) {
|
||||
int MetavoxelSystem::SimulateVisitor::visit(MetavoxelInfo& info) {
|
||||
SpannerVisitor::visit(info);
|
||||
|
||||
if (!info.isLeaf) {
|
||||
return true;
|
||||
return _order;
|
||||
}
|
||||
QRgb color = info.inputValues.at(0).getInlineValue<QRgb>();
|
||||
QRgb normal = info.inputValues.at(1).getInlineValue<QRgb>();
|
||||
|
@ -165,15 +167,16 @@ bool MetavoxelSystem::SimulateVisitor::visit(MetavoxelInfo& info) {
|
|||
{ qRed(color), qGreen(color), qBlue(color), alpha }, { qRed(normal), qGreen(normal), qBlue(normal) } };
|
||||
_points.append(point);
|
||||
}
|
||||
return false;
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
|
||||
MetavoxelSystem::RenderVisitor::RenderVisitor() :
|
||||
SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute()) {
|
||||
}
|
||||
|
||||
void MetavoxelSystem::RenderVisitor::visit(Spanner* spanner) {
|
||||
bool MetavoxelSystem::RenderVisitor::visit(Spanner* spanner) {
|
||||
spanner->getRenderer()->render(1.0f);
|
||||
return true;
|
||||
}
|
||||
|
||||
MetavoxelClient::MetavoxelClient(const SharedNodePointer& node) :
|
||||
|
@ -201,6 +204,16 @@ MetavoxelClient::~MetavoxelClient() {
|
|||
_sequencer.endPacket();
|
||||
}
|
||||
|
||||
static MetavoxelLOD getLOD() {
|
||||
const float FIXED_LOD_THRESHOLD = 0.01f;
|
||||
return MetavoxelLOD(Application::getInstance()->getCamera()->getPosition(), FIXED_LOD_THRESHOLD);
|
||||
}
|
||||
|
||||
void MetavoxelClient::guide(MetavoxelVisitor& visitor) {
|
||||
visitor.setLOD(getLOD());
|
||||
_data.guide(visitor);
|
||||
}
|
||||
|
||||
void MetavoxelClient::applyEdit(const MetavoxelEditMessage& edit) {
|
||||
// apply immediately to local tree
|
||||
edit.apply(_data);
|
||||
|
@ -211,8 +224,8 @@ void MetavoxelClient::applyEdit(const MetavoxelEditMessage& edit) {
|
|||
|
||||
void MetavoxelClient::simulate(float deltaTime) {
|
||||
Bitstream& out = _sequencer.startPacket();
|
||||
const float FIXED_LOD_THRESHOLD = 0.0001f;
|
||||
ClientStateMessage state = { MetavoxelLOD(Application::getInstance()->getCamera()->getPosition(), FIXED_LOD_THRESHOLD) };
|
||||
|
||||
ClientStateMessage state = { getLOD() };
|
||||
out << QVariant::fromValue(state);
|
||||
_sequencer.endPacket();
|
||||
|
||||
|
|
|
@ -57,18 +57,20 @@ private:
|
|||
public:
|
||||
SimulateVisitor(QVector<Point>& points);
|
||||
void setDeltaTime(float deltaTime) { _deltaTime = deltaTime; }
|
||||
virtual void visit(Spanner* spanner);
|
||||
virtual bool visit(MetavoxelInfo& info);
|
||||
void setOrder(const glm::vec3& direction) { _order = encodeOrder(direction); }
|
||||
virtual bool visit(Spanner* spanner);
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
|
||||
private:
|
||||
QVector<Point>& _points;
|
||||
float _deltaTime;
|
||||
int _order;
|
||||
};
|
||||
|
||||
class RenderVisitor : public SpannerVisitor {
|
||||
public:
|
||||
RenderVisitor();
|
||||
virtual void visit(Spanner* spanner);
|
||||
virtual bool visit(Spanner* spanner);
|
||||
};
|
||||
|
||||
static ProgramObject _program;
|
||||
|
@ -89,7 +91,7 @@ public:
|
|||
MetavoxelClient(const SharedNodePointer& node);
|
||||
virtual ~MetavoxelClient();
|
||||
|
||||
MetavoxelData& getData() { return _data; }
|
||||
void guide(MetavoxelVisitor& visitor);
|
||||
|
||||
void applyEdit(const MetavoxelEditMessage& edit);
|
||||
|
||||
|
|
|
@ -32,7 +32,19 @@ bool MetavoxelLOD::shouldSubdivide(const glm::vec3& minimum, float size) const {
|
|||
}
|
||||
|
||||
bool MetavoxelLOD::becameSubdivided(const glm::vec3& minimum, float size, const MetavoxelLOD& reference) const {
|
||||
return shouldSubdivide(minimum, size) && !reference.shouldSubdivide(minimum, size);
|
||||
if (position == reference.position && threshold >= reference.threshold) {
|
||||
return false; // first off, nothing becomes subdivided if it doesn't change
|
||||
}
|
||||
if (!shouldSubdivide(minimum, size)) {
|
||||
return false; // this one must be subdivided
|
||||
}
|
||||
// the general check is whether we've gotten closer (as multiplied by the threshold) to any point in the volume,
|
||||
// which we approximate as a sphere for simplicity
|
||||
float halfSize = size * 0.5f;
|
||||
glm::vec3 center = minimum + glm::vec3(halfSize, halfSize, halfSize);
|
||||
float radius = sqrtf(3 * halfSize * halfSize);
|
||||
return qMax(0.0f, glm::distance(position, center) - radius) * threshold <=
|
||||
qMax(0.0f, glm::distance(reference.position, center) - radius) * reference.threshold;
|
||||
}
|
||||
|
||||
MetavoxelData::MetavoxelData() : _size(1.0f) {
|
||||
|
@ -128,7 +140,7 @@ public:
|
|||
SpannerUpdateVisitor(const AttributePointer& attribute, const Box& bounds,
|
||||
float granularity, const SharedObjectPointer& object);
|
||||
|
||||
virtual bool visit(MetavoxelInfo& info);
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -147,17 +159,17 @@ template<SpannerUpdateFunction F> SpannerUpdateVisitor<F>::SpannerUpdateVisitor(
|
|||
_object(object) {
|
||||
}
|
||||
|
||||
template<SpannerUpdateFunction F> bool SpannerUpdateVisitor<F>::visit(MetavoxelInfo& info) {
|
||||
template<SpannerUpdateFunction F> int SpannerUpdateVisitor<F>::visit(MetavoxelInfo& info) {
|
||||
if (!info.getBounds().intersects(_bounds)) {
|
||||
return false;
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
if (info.size > _longestSide) {
|
||||
return true;
|
||||
return DEFAULT_ORDER;
|
||||
}
|
||||
SharedObjectSet set = info.inputValues.at(0).getInlineValue<SharedObjectSet>();
|
||||
F(set, _object);
|
||||
info.outputValues[0] = AttributeValue(_attribute, encodeInline(set));
|
||||
return false;
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
|
||||
void MetavoxelData::insert(const AttributePointer& attribute, const SharedObjectPointer& object) {
|
||||
|
@ -737,9 +749,43 @@ void MetavoxelNode::clearChildren(const AttributePointer& attribute) {
|
|||
}
|
||||
}
|
||||
|
||||
MetavoxelVisitor::MetavoxelVisitor(const QVector<AttributePointer>& inputs, const QVector<AttributePointer>& outputs) :
|
||||
int MetavoxelVisitor::encodeOrder(int first, int second, int third, int fourth,
|
||||
int fifth, int sixth, int seventh, int eighth) {
|
||||
return first | (second << 3) | (third << 6) | (fourth << 9) |
|
||||
(fifth << 12) | (sixth << 15) | (seventh << 18) | (eighth << 21);
|
||||
}
|
||||
|
||||
class IndexDistance {
|
||||
public:
|
||||
int index;
|
||||
float distance;
|
||||
};
|
||||
|
||||
bool operator<(const IndexDistance& first, const IndexDistance& second) {
|
||||
return first.distance < second.distance;
|
||||
}
|
||||
|
||||
int MetavoxelVisitor::encodeOrder(const glm::vec3& direction) {
|
||||
QList<IndexDistance> indexDistances;
|
||||
for (int i = 0; i < MetavoxelNode::CHILD_COUNT; i++) {
|
||||
IndexDistance indexDistance = { i, glm::dot(direction, getNextMinimum(glm::vec3(), 1.0f, i)) };
|
||||
indexDistances.append(indexDistance);
|
||||
}
|
||||
qStableSort(indexDistances);
|
||||
return encodeOrder(indexDistances.at(0).index, indexDistances.at(1).index, indexDistances.at(2).index,
|
||||
indexDistances.at(3).index, indexDistances.at(4).index, indexDistances.at(5).index,
|
||||
indexDistances.at(6).index, indexDistances.at(7).index);
|
||||
}
|
||||
|
||||
const int MetavoxelVisitor::DEFAULT_ORDER = encodeOrder(0, 1, 2, 3, 4, 5, 6, 7);
|
||||
const int MetavoxelVisitor::STOP_RECURSION = 0;
|
||||
const int MetavoxelVisitor::SHORT_CIRCUIT = -1;
|
||||
|
||||
MetavoxelVisitor::MetavoxelVisitor(const QVector<AttributePointer>& inputs,
|
||||
const QVector<AttributePointer>& outputs, const MetavoxelLOD& lod) :
|
||||
_inputs(inputs),
|
||||
_outputs(outputs) {
|
||||
_outputs(outputs),
|
||||
_lod(lod) {
|
||||
}
|
||||
|
||||
MetavoxelVisitor::~MetavoxelVisitor() {
|
||||
|
@ -750,8 +796,8 @@ void MetavoxelVisitor::prepare() {
|
|||
}
|
||||
|
||||
SpannerVisitor::SpannerVisitor(const QVector<AttributePointer>& spannerInputs, const QVector<AttributePointer>& inputs,
|
||||
const QVector<AttributePointer>& outputs) :
|
||||
MetavoxelVisitor(inputs + spannerInputs, outputs),
|
||||
const QVector<AttributePointer>& outputs, const MetavoxelLOD& lod) :
|
||||
MetavoxelVisitor(inputs + spannerInputs, outputs, lod),
|
||||
_spannerInputCount(spannerInputs.size()) {
|
||||
}
|
||||
|
||||
|
@ -759,24 +805,30 @@ void SpannerVisitor::prepare() {
|
|||
Spanner::incrementVisit();
|
||||
}
|
||||
|
||||
bool SpannerVisitor::visit(MetavoxelInfo& info) {
|
||||
int SpannerVisitor::visit(MetavoxelInfo& info) {
|
||||
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()) {
|
||||
visit(spanner);
|
||||
if (!visit(spanner)) {
|
||||
return SHORT_CIRCUIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return !info.isLeaf;
|
||||
return info.isLeaf ? STOP_RECURSION : DEFAULT_ORDER;
|
||||
}
|
||||
|
||||
DefaultMetavoxelGuide::DefaultMetavoxelGuide() {
|
||||
}
|
||||
|
||||
void DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
||||
visitation.info.isLeaf = visitation.allInputNodesLeaves();
|
||||
bool keepGoing = visitation.visitor.visit(visitation.info);
|
||||
bool DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
||||
bool shouldSubdivide = visitation.visitor.getLOD().shouldSubdivide(visitation.info.minimum, visitation.info.size);
|
||||
visitation.info.isLeaf = !shouldSubdivide || visitation.allInputNodesLeaves();
|
||||
int encodedOrder = visitation.visitor.visit(visitation.info);
|
||||
if (encodedOrder == MetavoxelVisitor::SHORT_CIRCUIT) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < visitation.outputNodes.size(); i++) {
|
||||
OwnedAttributeValue& value = visitation.info.outputValues[i];
|
||||
if (!value.getAttribute()) {
|
||||
|
@ -790,29 +842,35 @@ void DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
|||
node = new MetavoxelNode(value);
|
||||
}
|
||||
}
|
||||
if (!keepGoing) {
|
||||
return;
|
||||
if (encodedOrder == MetavoxelVisitor::STOP_RECURSION) {
|
||||
return true;
|
||||
}
|
||||
MetavoxelVisitation nextVisitation = { &visitation, visitation.visitor,
|
||||
QVector<MetavoxelNode*>(visitation.inputNodes.size()), QVector<MetavoxelNode*>(visitation.outputNodes.size()),
|
||||
{ glm::vec3(), visitation.info.size * 0.5f, QVector<AttributeValue>(visitation.inputNodes.size()),
|
||||
QVector<OwnedAttributeValue>(visitation.outputNodes.size()) } };
|
||||
for (int i = 0; i < MetavoxelNode::CHILD_COUNT; i++) {
|
||||
const int ORDER_ELEMENT_BITS = 3;
|
||||
const int ORDER_ELEMENT_MASK = (1 << ORDER_ELEMENT_BITS) - 1;
|
||||
int index = encodedOrder & ORDER_ELEMENT_MASK;
|
||||
encodedOrder >>= ORDER_ELEMENT_BITS;
|
||||
for (int j = 0; j < visitation.inputNodes.size(); j++) {
|
||||
MetavoxelNode* node = visitation.inputNodes.at(j);
|
||||
MetavoxelNode* child = node ? node->getChild(i) : NULL;
|
||||
MetavoxelNode* child = (node && shouldSubdivide) ? node->getChild(index) : NULL;
|
||||
nextVisitation.info.inputValues[j] = ((nextVisitation.inputNodes[j] = child)) ?
|
||||
child->getAttributeValue(visitation.info.inputValues[j].getAttribute()) :
|
||||
visitation.info.inputValues[j];
|
||||
}
|
||||
for (int j = 0; j < visitation.outputNodes.size(); j++) {
|
||||
MetavoxelNode* node = visitation.outputNodes.at(j);
|
||||
MetavoxelNode* child = node ? node->getChild(i) : NULL;
|
||||
MetavoxelNode* child = (node && shouldSubdivide) ? node->getChild(index) : NULL;
|
||||
nextVisitation.outputNodes[j] = child;
|
||||
}
|
||||
nextVisitation.info.minimum = getNextMinimum(visitation.info.minimum, nextVisitation.info.size, i);
|
||||
static_cast<MetavoxelGuide*>(nextVisitation.info.inputValues.last().getInlineValue<
|
||||
SharedObjectPointer>().data())->guide(nextVisitation);
|
||||
nextVisitation.info.minimum = getNextMinimum(visitation.info.minimum, nextVisitation.info.size, index);
|
||||
if (!static_cast<MetavoxelGuide*>(nextVisitation.info.inputValues.last().getInlineValue<
|
||||
SharedObjectPointer>().data())->guide(nextVisitation)) {
|
||||
return false;
|
||||
}
|
||||
for (int j = 0; j < nextVisitation.outputNodes.size(); j++) {
|
||||
OwnedAttributeValue& value = nextVisitation.info.outputValues[j];
|
||||
if (!value.getAttribute()) {
|
||||
|
@ -839,10 +897,10 @@ void DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
|||
// it's a leaf; we need to split it up
|
||||
AttributeValue nodeValue = node->getAttributeValue(value.getAttribute());
|
||||
for (int k = 1; k < MetavoxelNode::CHILD_COUNT; k++) {
|
||||
node->setChild((i + k) % MetavoxelNode::CHILD_COUNT, new MetavoxelNode(nodeValue));
|
||||
node->setChild((index + k) % MetavoxelNode::CHILD_COUNT, new MetavoxelNode(nodeValue));
|
||||
}
|
||||
}
|
||||
node->setChild(i, nextVisitation.outputNodes.at(j));
|
||||
node->setChild(index, nextVisitation.outputNodes.at(j));
|
||||
value = AttributeValue();
|
||||
}
|
||||
}
|
||||
|
@ -854,12 +912,13 @@ void DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
|||
value = node->getAttributeValue(value.getAttribute());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ThrobbingMetavoxelGuide::ThrobbingMetavoxelGuide() : _rate(10.0) {
|
||||
}
|
||||
|
||||
void ThrobbingMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
||||
bool ThrobbingMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
||||
AttributePointer colorAttribute = AttributeRegistry::getInstance()->getColorAttribute();
|
||||
for (int i = 0; i < visitation.info.inputValues.size(); i++) {
|
||||
AttributeValue& attributeValue = visitation.info.inputValues[i];
|
||||
|
@ -872,7 +931,7 @@ void ThrobbingMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
|||
}
|
||||
}
|
||||
|
||||
DefaultMetavoxelGuide::guide(visitation);
|
||||
return DefaultMetavoxelGuide::guide(visitation);
|
||||
}
|
||||
|
||||
static QScriptValue getAttributes(QScriptEngine* engine, ScriptedMetavoxelGuide* guide,
|
||||
|
@ -933,7 +992,7 @@ QScriptValue ScriptedMetavoxelGuide::visit(QScriptContext* context, QScriptEngin
|
|||
ScriptedMetavoxelGuide::ScriptedMetavoxelGuide() {
|
||||
}
|
||||
|
||||
void ScriptedMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
||||
bool ScriptedMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
||||
QScriptValue guideFunction;
|
||||
if (_guideFunction) {
|
||||
guideFunction = _guideFunction->getValue();
|
||||
|
@ -944,8 +1003,7 @@ void ScriptedMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
|||
}
|
||||
if (!guideFunction.isValid()) {
|
||||
// before we load, just use the default behavior
|
||||
DefaultMetavoxelGuide::guide(visitation);
|
||||
return;
|
||||
return DefaultMetavoxelGuide::guide(visitation);
|
||||
}
|
||||
QScriptEngine* engine = guideFunction.engine();
|
||||
if (!_minimumHandle.isValid()) {
|
||||
|
@ -983,6 +1041,7 @@ void ScriptedMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
|||
if (engine->hasUncaughtException()) {
|
||||
qDebug() << "Script error: " << engine->uncaughtException().toString();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScriptedMetavoxelGuide::setURL(const ParameterizedURL& url) {
|
||||
|
|
|
@ -194,8 +194,24 @@ public:
|
|||
class MetavoxelVisitor {
|
||||
public:
|
||||
|
||||
/// Encodes a visitation order sequence for the children of a metavoxel.
|
||||
static int encodeOrder(int first, int second, int third, int fourth, int fifth, int sixth, int seventh, int eighth);
|
||||
|
||||
/// Encodes a visitation order sequence that visits each child as sorted along the specified direction.
|
||||
static int encodeOrder(const glm::vec3& direction);
|
||||
|
||||
/// The default visitation order.
|
||||
static const int DEFAULT_ORDER;
|
||||
|
||||
/// A special "order" that instructs the guide to stop recursion.
|
||||
static const int STOP_RECURSION;
|
||||
|
||||
/// A special "order" that short-circuits the tour.
|
||||
static const int SHORT_CIRCUIT;
|
||||
|
||||
MetavoxelVisitor(const QVector<AttributePointer>& inputs,
|
||||
const QVector<AttributePointer>& outputs = QVector<AttributePointer>());
|
||||
const QVector<AttributePointer>& outputs = QVector<AttributePointer>(),
|
||||
const MetavoxelLOD& lod = MetavoxelLOD());
|
||||
virtual ~MetavoxelVisitor();
|
||||
|
||||
/// Returns a reference to the list of input attributes desired.
|
||||
|
@ -204,18 +220,24 @@ public:
|
|||
/// Returns a reference to the list of output attributes provided.
|
||||
const QVector<AttributePointer>& getOutputs() const { return _outputs; }
|
||||
|
||||
/// Returns a reference to the level of detail that will determine subdivision levels.
|
||||
const MetavoxelLOD& getLOD() const { return _lod; }
|
||||
|
||||
void setLOD(const MetavoxelLOD& lod) { _lod = lod; }
|
||||
|
||||
/// Prepares for a new tour of the metavoxel data.
|
||||
virtual void prepare();
|
||||
|
||||
/// Visits a metavoxel.
|
||||
/// \param info the metavoxel data
|
||||
/// \return if true, continue descending; if false, stop
|
||||
virtual bool visit(MetavoxelInfo& info) = 0;
|
||||
/// \return the encoded order in which to traverse the children, zero to stop recursion, or -1 to short-circuit the tour
|
||||
virtual int visit(MetavoxelInfo& info) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
QVector<AttributePointer> _inputs;
|
||||
QVector<AttributePointer> _outputs;
|
||||
MetavoxelLOD _lod;
|
||||
};
|
||||
|
||||
typedef QSharedPointer<MetavoxelVisitor> MetavoxelVisitorPointer;
|
||||
|
@ -226,13 +248,15 @@ public:
|
|||
|
||||
SpannerVisitor(const QVector<AttributePointer>& spannerInputs,
|
||||
const QVector<AttributePointer>& inputs = QVector<AttributePointer>(),
|
||||
const QVector<AttributePointer>& outputs = QVector<AttributePointer>());
|
||||
const QVector<AttributePointer>& outputs = QVector<AttributePointer>(),
|
||||
const MetavoxelLOD& lod = MetavoxelLOD());
|
||||
|
||||
/// Visits a spanner.
|
||||
virtual void visit(Spanner* spanner) = 0;
|
||||
/// \return true to continue, false to short-circuit the tour
|
||||
virtual bool visit(Spanner* spanner) = 0;
|
||||
|
||||
virtual void prepare();
|
||||
virtual bool visit(MetavoxelInfo& info);
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -246,7 +270,8 @@ class MetavoxelGuide : public SharedObject {
|
|||
public:
|
||||
|
||||
/// Guides the specified visitor to the contained voxels.
|
||||
virtual void guide(MetavoxelVisitation& visitation) = 0;
|
||||
/// \return true to keep going, false to short circuit the tour
|
||||
virtual bool guide(MetavoxelVisitation& visitation) = 0;
|
||||
};
|
||||
|
||||
/// Guides visitors through the explicit content of the system.
|
||||
|
@ -257,7 +282,7 @@ public:
|
|||
|
||||
Q_INVOKABLE DefaultMetavoxelGuide();
|
||||
|
||||
virtual void guide(MetavoxelVisitation& visitation);
|
||||
virtual bool guide(MetavoxelVisitation& visitation);
|
||||
};
|
||||
|
||||
/// A temporary test guide that just makes the existing voxels throb with delight.
|
||||
|
@ -269,7 +294,7 @@ public:
|
|||
|
||||
Q_INVOKABLE ThrobbingMetavoxelGuide();
|
||||
|
||||
virtual void guide(MetavoxelVisitation& visitation);
|
||||
virtual bool guide(MetavoxelVisitation& visitation);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -285,7 +310,7 @@ public:
|
|||
|
||||
Q_INVOKABLE ScriptedMetavoxelGuide();
|
||||
|
||||
virtual void guide(MetavoxelVisitation& visitation);
|
||||
virtual bool guide(MetavoxelVisitation& visitation);
|
||||
|
||||
public slots:
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ public:
|
|||
|
||||
BoxSetEditVisitor(const BoxSetEdit& edit);
|
||||
|
||||
virtual bool visit(MetavoxelInfo& info);
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -36,26 +36,26 @@ BoxSetEditVisitor::BoxSetEditVisitor(const BoxSetEdit& edit) :
|
|||
_edit(edit) {
|
||||
}
|
||||
|
||||
bool BoxSetEditVisitor::visit(MetavoxelInfo& info) {
|
||||
int BoxSetEditVisitor::visit(MetavoxelInfo& info) {
|
||||
// find the intersection between volume and voxel
|
||||
glm::vec3 minimum = glm::max(info.minimum, _edit.region.minimum);
|
||||
glm::vec3 maximum = glm::min(info.minimum + glm::vec3(info.size, info.size, info.size), _edit.region.maximum);
|
||||
glm::vec3 size = maximum - minimum;
|
||||
if (size.x <= 0.0f || size.y <= 0.0f || size.z <= 0.0f) {
|
||||
return false; // disjoint
|
||||
return STOP_RECURSION; // disjoint
|
||||
}
|
||||
float volume = (size.x * size.y * size.z) / (info.size * info.size * info.size);
|
||||
if (volume >= 1.0f) {
|
||||
info.outputValues[0] = _edit.value;
|
||||
return false; // entirely contained
|
||||
return STOP_RECURSION; // entirely contained
|
||||
}
|
||||
if (info.size <= _edit.granularity) {
|
||||
if (volume >= 0.5f) {
|
||||
info.outputValues[0] = _edit.value;
|
||||
}
|
||||
return false; // reached granularity limit; take best guess
|
||||
return STOP_RECURSION; // reached granularity limit; take best guess
|
||||
}
|
||||
return true; // subdivide
|
||||
return DEFAULT_ORDER; // subdivide
|
||||
}
|
||||
|
||||
void BoxSetEdit::apply(MetavoxelData& data) const {
|
||||
|
@ -77,7 +77,7 @@ public:
|
|||
|
||||
GlobalSetEditVisitor(const GlobalSetEdit& edit);
|
||||
|
||||
virtual bool visit(MetavoxelInfo& info);
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -89,9 +89,9 @@ GlobalSetEditVisitor::GlobalSetEditVisitor(const GlobalSetEdit& edit) :
|
|||
_edit(edit) {
|
||||
}
|
||||
|
||||
bool GlobalSetEditVisitor::visit(MetavoxelInfo& info) {
|
||||
int GlobalSetEditVisitor::visit(MetavoxelInfo& info) {
|
||||
info.outputValues[0] = _edit.value;
|
||||
return false; // entirely contained
|
||||
return STOP_RECURSION; // entirely contained
|
||||
}
|
||||
|
||||
void GlobalSetEdit::apply(MetavoxelData& data) const {
|
||||
|
|
Loading…
Reference in a new issue