mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-29 20:42:56 +02:00
Ordered visitation bits.
This commit is contained in:
parent
c4f29005a0
commit
60b0281095
5 changed files with 162 additions and 63 deletions
|
@ -61,13 +61,14 @@ void MetavoxelSystem::simulate(float deltaTime) {
|
||||||
// simulate the clients
|
// simulate the clients
|
||||||
_points.clear();
|
_points.clear();
|
||||||
_simulateVisitor.setDeltaTime(deltaTime);
|
_simulateVisitor.setDeltaTime(deltaTime);
|
||||||
|
_simulateVisitor.setOrder(-Application::getInstance()->getViewFrustum()->getDirection());
|
||||||
foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
|
foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
|
||||||
if (node->getType() == NodeType::MetavoxelServer) {
|
if (node->getType() == NodeType::MetavoxelServer) {
|
||||||
QMutexLocker locker(&node->getMutex());
|
QMutexLocker locker(&node->getMutex());
|
||||||
MetavoxelClient* client = static_cast<MetavoxelClient*>(node->getLinkedData());
|
MetavoxelClient* client = static_cast<MetavoxelClient*>(node->getLinkedData());
|
||||||
if (client) {
|
if (client) {
|
||||||
client->simulate(deltaTime);
|
client->simulate(deltaTime);
|
||||||
client->getData().guide(_simulateVisitor);
|
client->guide(_simulateVisitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,7 +128,7 @@ void MetavoxelSystem::render() {
|
||||||
QMutexLocker locker(&node->getMutex());
|
QMutexLocker locker(&node->getMutex());
|
||||||
MetavoxelClient* client = static_cast<MetavoxelClient*>(node->getLinkedData());
|
MetavoxelClient* client = static_cast<MetavoxelClient*>(node->getLinkedData());
|
||||||
if (client) {
|
if (client) {
|
||||||
client->getData().guide(_renderVisitor);
|
client->guide(_renderVisitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,15 +148,16 @@ MetavoxelSystem::SimulateVisitor::SimulateVisitor(QVector<Point>& points) :
|
||||||
_points(points) {
|
_points(points) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetavoxelSystem::SimulateVisitor::visit(Spanner* spanner) {
|
bool MetavoxelSystem::SimulateVisitor::visit(Spanner* spanner) {
|
||||||
spanner->getRenderer()->simulate(_deltaTime);
|
spanner->getRenderer()->simulate(_deltaTime);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MetavoxelSystem::SimulateVisitor::visit(MetavoxelInfo& info) {
|
int MetavoxelSystem::SimulateVisitor::visit(MetavoxelInfo& info) {
|
||||||
SpannerVisitor::visit(info);
|
SpannerVisitor::visit(info);
|
||||||
|
|
||||||
if (!info.isLeaf) {
|
if (!info.isLeaf) {
|
||||||
return true;
|
return _order;
|
||||||
}
|
}
|
||||||
QRgb color = info.inputValues.at(0).getInlineValue<QRgb>();
|
QRgb color = info.inputValues.at(0).getInlineValue<QRgb>();
|
||||||
QRgb normal = info.inputValues.at(1).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) } };
|
{ qRed(color), qGreen(color), qBlue(color), alpha }, { qRed(normal), qGreen(normal), qBlue(normal) } };
|
||||||
_points.append(point);
|
_points.append(point);
|
||||||
}
|
}
|
||||||
return false;
|
return STOP_RECURSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
MetavoxelSystem::RenderVisitor::RenderVisitor() :
|
MetavoxelSystem::RenderVisitor::RenderVisitor() :
|
||||||
SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute()) {
|
SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetavoxelSystem::RenderVisitor::visit(Spanner* spanner) {
|
bool MetavoxelSystem::RenderVisitor::visit(Spanner* spanner) {
|
||||||
spanner->getRenderer()->render(1.0f);
|
spanner->getRenderer()->render(1.0f);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MetavoxelClient::MetavoxelClient(const SharedNodePointer& node) :
|
MetavoxelClient::MetavoxelClient(const SharedNodePointer& node) :
|
||||||
|
@ -201,6 +204,16 @@ MetavoxelClient::~MetavoxelClient() {
|
||||||
_sequencer.endPacket();
|
_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) {
|
void MetavoxelClient::applyEdit(const MetavoxelEditMessage& edit) {
|
||||||
// apply immediately to local tree
|
// apply immediately to local tree
|
||||||
edit.apply(_data);
|
edit.apply(_data);
|
||||||
|
@ -211,8 +224,8 @@ void MetavoxelClient::applyEdit(const MetavoxelEditMessage& edit) {
|
||||||
|
|
||||||
void MetavoxelClient::simulate(float deltaTime) {
|
void MetavoxelClient::simulate(float deltaTime) {
|
||||||
Bitstream& out = _sequencer.startPacket();
|
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);
|
out << QVariant::fromValue(state);
|
||||||
_sequencer.endPacket();
|
_sequencer.endPacket();
|
||||||
|
|
||||||
|
|
|
@ -57,18 +57,20 @@ private:
|
||||||
public:
|
public:
|
||||||
SimulateVisitor(QVector<Point>& points);
|
SimulateVisitor(QVector<Point>& points);
|
||||||
void setDeltaTime(float deltaTime) { _deltaTime = deltaTime; }
|
void setDeltaTime(float deltaTime) { _deltaTime = deltaTime; }
|
||||||
virtual void visit(Spanner* spanner);
|
void setOrder(const glm::vec3& direction) { _order = encodeOrder(direction); }
|
||||||
virtual bool visit(MetavoxelInfo& info);
|
virtual bool visit(Spanner* spanner);
|
||||||
|
virtual int visit(MetavoxelInfo& info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVector<Point>& _points;
|
QVector<Point>& _points;
|
||||||
float _deltaTime;
|
float _deltaTime;
|
||||||
|
int _order;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RenderVisitor : public SpannerVisitor {
|
class RenderVisitor : public SpannerVisitor {
|
||||||
public:
|
public:
|
||||||
RenderVisitor();
|
RenderVisitor();
|
||||||
virtual void visit(Spanner* spanner);
|
virtual bool visit(Spanner* spanner);
|
||||||
};
|
};
|
||||||
|
|
||||||
static ProgramObject _program;
|
static ProgramObject _program;
|
||||||
|
@ -89,7 +91,7 @@ public:
|
||||||
MetavoxelClient(const SharedNodePointer& node);
|
MetavoxelClient(const SharedNodePointer& node);
|
||||||
virtual ~MetavoxelClient();
|
virtual ~MetavoxelClient();
|
||||||
|
|
||||||
MetavoxelData& getData() { return _data; }
|
void guide(MetavoxelVisitor& visitor);
|
||||||
|
|
||||||
void applyEdit(const MetavoxelEditMessage& edit);
|
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 {
|
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) {
|
MetavoxelData::MetavoxelData() : _size(1.0f) {
|
||||||
|
@ -128,7 +140,7 @@ public:
|
||||||
SpannerUpdateVisitor(const AttributePointer& attribute, const Box& bounds,
|
SpannerUpdateVisitor(const AttributePointer& attribute, const Box& bounds,
|
||||||
float granularity, const SharedObjectPointer& object);
|
float granularity, const SharedObjectPointer& object);
|
||||||
|
|
||||||
virtual bool visit(MetavoxelInfo& info);
|
virtual int visit(MetavoxelInfo& info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -147,17 +159,17 @@ template<SpannerUpdateFunction F> SpannerUpdateVisitor<F>::SpannerUpdateVisitor(
|
||||||
_object(object) {
|
_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)) {
|
if (!info.getBounds().intersects(_bounds)) {
|
||||||
return false;
|
return STOP_RECURSION;
|
||||||
}
|
}
|
||||||
if (info.size > _longestSide) {
|
if (info.size > _longestSide) {
|
||||||
return true;
|
return DEFAULT_ORDER;
|
||||||
}
|
}
|
||||||
SharedObjectSet set = info.inputValues.at(0).getInlineValue<SharedObjectSet>();
|
SharedObjectSet set = info.inputValues.at(0).getInlineValue<SharedObjectSet>();
|
||||||
F(set, _object);
|
F(set, _object);
|
||||||
info.outputValues[0] = AttributeValue(_attribute, encodeInline(set));
|
info.outputValues[0] = AttributeValue(_attribute, encodeInline(set));
|
||||||
return false;
|
return STOP_RECURSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetavoxelData::insert(const AttributePointer& attribute, const SharedObjectPointer& object) {
|
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),
|
_inputs(inputs),
|
||||||
_outputs(outputs) {
|
_outputs(outputs),
|
||||||
|
_lod(lod) {
|
||||||
}
|
}
|
||||||
|
|
||||||
MetavoxelVisitor::~MetavoxelVisitor() {
|
MetavoxelVisitor::~MetavoxelVisitor() {
|
||||||
|
@ -750,8 +796,8 @@ void MetavoxelVisitor::prepare() {
|
||||||
}
|
}
|
||||||
|
|
||||||
SpannerVisitor::SpannerVisitor(const QVector<AttributePointer>& spannerInputs, const QVector<AttributePointer>& inputs,
|
SpannerVisitor::SpannerVisitor(const QVector<AttributePointer>& spannerInputs, const QVector<AttributePointer>& inputs,
|
||||||
const QVector<AttributePointer>& outputs) :
|
const QVector<AttributePointer>& outputs, const MetavoxelLOD& lod) :
|
||||||
MetavoxelVisitor(inputs + spannerInputs, outputs),
|
MetavoxelVisitor(inputs + spannerInputs, outputs, lod),
|
||||||
_spannerInputCount(spannerInputs.size()) {
|
_spannerInputCount(spannerInputs.size()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -759,24 +805,30 @@ void SpannerVisitor::prepare() {
|
||||||
Spanner::incrementVisit();
|
Spanner::incrementVisit();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SpannerVisitor::visit(MetavoxelInfo& info) {
|
int SpannerVisitor::visit(MetavoxelInfo& info) {
|
||||||
for (int i = _inputs.size() - _spannerInputCount; i < _inputs.size(); i++) {
|
for (int i = _inputs.size() - _spannerInputCount; i < _inputs.size(); i++) {
|
||||||
foreach (const SharedObjectPointer& object, info.inputValues.at(i).getInlineValue<SharedObjectSet>()) {
|
foreach (const SharedObjectPointer& object, info.inputValues.at(i).getInlineValue<SharedObjectSet>()) {
|
||||||
Spanner* spanner = static_cast<Spanner*>(object.data());
|
Spanner* spanner = static_cast<Spanner*>(object.data());
|
||||||
if (spanner->testAndSetVisited()) {
|
if (spanner->testAndSetVisited()) {
|
||||||
visit(spanner);
|
if (!visit(spanner)) {
|
||||||
|
return SHORT_CIRCUIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return !info.isLeaf;
|
}
|
||||||
|
return info.isLeaf ? STOP_RECURSION : DEFAULT_ORDER;
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultMetavoxelGuide::DefaultMetavoxelGuide() {
|
DefaultMetavoxelGuide::DefaultMetavoxelGuide() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
bool DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
||||||
visitation.info.isLeaf = visitation.allInputNodesLeaves();
|
bool shouldSubdivide = visitation.visitor.getLOD().shouldSubdivide(visitation.info.minimum, visitation.info.size);
|
||||||
bool keepGoing = visitation.visitor.visit(visitation.info);
|
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++) {
|
for (int i = 0; i < visitation.outputNodes.size(); i++) {
|
||||||
OwnedAttributeValue& value = visitation.info.outputValues[i];
|
OwnedAttributeValue& value = visitation.info.outputValues[i];
|
||||||
if (!value.getAttribute()) {
|
if (!value.getAttribute()) {
|
||||||
|
@ -790,29 +842,35 @@ void DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
||||||
node = new MetavoxelNode(value);
|
node = new MetavoxelNode(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!keepGoing) {
|
if (encodedOrder == MetavoxelVisitor::STOP_RECURSION) {
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
MetavoxelVisitation nextVisitation = { &visitation, visitation.visitor,
|
MetavoxelVisitation nextVisitation = { &visitation, visitation.visitor,
|
||||||
QVector<MetavoxelNode*>(visitation.inputNodes.size()), QVector<MetavoxelNode*>(visitation.outputNodes.size()),
|
QVector<MetavoxelNode*>(visitation.inputNodes.size()), QVector<MetavoxelNode*>(visitation.outputNodes.size()),
|
||||||
{ glm::vec3(), visitation.info.size * 0.5f, QVector<AttributeValue>(visitation.inputNodes.size()),
|
{ glm::vec3(), visitation.info.size * 0.5f, QVector<AttributeValue>(visitation.inputNodes.size()),
|
||||||
QVector<OwnedAttributeValue>(visitation.outputNodes.size()) } };
|
QVector<OwnedAttributeValue>(visitation.outputNodes.size()) } };
|
||||||
for (int i = 0; i < MetavoxelNode::CHILD_COUNT; i++) {
|
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++) {
|
for (int j = 0; j < visitation.inputNodes.size(); j++) {
|
||||||
MetavoxelNode* node = visitation.inputNodes.at(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)) ?
|
nextVisitation.info.inputValues[j] = ((nextVisitation.inputNodes[j] = child)) ?
|
||||||
child->getAttributeValue(visitation.info.inputValues[j].getAttribute()) :
|
child->getAttributeValue(visitation.info.inputValues[j].getAttribute()) :
|
||||||
visitation.info.inputValues[j];
|
visitation.info.inputValues[j];
|
||||||
}
|
}
|
||||||
for (int j = 0; j < visitation.outputNodes.size(); j++) {
|
for (int j = 0; j < visitation.outputNodes.size(); j++) {
|
||||||
MetavoxelNode* node = visitation.outputNodes.at(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.outputNodes[j] = child;
|
||||||
}
|
}
|
||||||
nextVisitation.info.minimum = getNextMinimum(visitation.info.minimum, nextVisitation.info.size, i);
|
nextVisitation.info.minimum = getNextMinimum(visitation.info.minimum, nextVisitation.info.size, index);
|
||||||
static_cast<MetavoxelGuide*>(nextVisitation.info.inputValues.last().getInlineValue<
|
if (!static_cast<MetavoxelGuide*>(nextVisitation.info.inputValues.last().getInlineValue<
|
||||||
SharedObjectPointer>().data())->guide(nextVisitation);
|
SharedObjectPointer>().data())->guide(nextVisitation)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
for (int j = 0; j < nextVisitation.outputNodes.size(); j++) {
|
for (int j = 0; j < nextVisitation.outputNodes.size(); j++) {
|
||||||
OwnedAttributeValue& value = nextVisitation.info.outputValues[j];
|
OwnedAttributeValue& value = nextVisitation.info.outputValues[j];
|
||||||
if (!value.getAttribute()) {
|
if (!value.getAttribute()) {
|
||||||
|
@ -839,10 +897,10 @@ void DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
||||||
// it's a leaf; we need to split it up
|
// it's a leaf; we need to split it up
|
||||||
AttributeValue nodeValue = node->getAttributeValue(value.getAttribute());
|
AttributeValue nodeValue = node->getAttributeValue(value.getAttribute());
|
||||||
for (int k = 1; k < MetavoxelNode::CHILD_COUNT; k++) {
|
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();
|
value = AttributeValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -854,12 +912,13 @@ void DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
||||||
value = node->getAttributeValue(value.getAttribute());
|
value = node->getAttributeValue(value.getAttribute());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrobbingMetavoxelGuide::ThrobbingMetavoxelGuide() : _rate(10.0) {
|
ThrobbingMetavoxelGuide::ThrobbingMetavoxelGuide() : _rate(10.0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThrobbingMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
bool ThrobbingMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
||||||
AttributePointer colorAttribute = AttributeRegistry::getInstance()->getColorAttribute();
|
AttributePointer colorAttribute = AttributeRegistry::getInstance()->getColorAttribute();
|
||||||
for (int i = 0; i < visitation.info.inputValues.size(); i++) {
|
for (int i = 0; i < visitation.info.inputValues.size(); i++) {
|
||||||
AttributeValue& attributeValue = visitation.info.inputValues[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,
|
static QScriptValue getAttributes(QScriptEngine* engine, ScriptedMetavoxelGuide* guide,
|
||||||
|
@ -933,7 +992,7 @@ QScriptValue ScriptedMetavoxelGuide::visit(QScriptContext* context, QScriptEngin
|
||||||
ScriptedMetavoxelGuide::ScriptedMetavoxelGuide() {
|
ScriptedMetavoxelGuide::ScriptedMetavoxelGuide() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptedMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
bool ScriptedMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
||||||
QScriptValue guideFunction;
|
QScriptValue guideFunction;
|
||||||
if (_guideFunction) {
|
if (_guideFunction) {
|
||||||
guideFunction = _guideFunction->getValue();
|
guideFunction = _guideFunction->getValue();
|
||||||
|
@ -944,8 +1003,7 @@ void ScriptedMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
||||||
}
|
}
|
||||||
if (!guideFunction.isValid()) {
|
if (!guideFunction.isValid()) {
|
||||||
// before we load, just use the default behavior
|
// before we load, just use the default behavior
|
||||||
DefaultMetavoxelGuide::guide(visitation);
|
return DefaultMetavoxelGuide::guide(visitation);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
QScriptEngine* engine = guideFunction.engine();
|
QScriptEngine* engine = guideFunction.engine();
|
||||||
if (!_minimumHandle.isValid()) {
|
if (!_minimumHandle.isValid()) {
|
||||||
|
@ -983,6 +1041,7 @@ void ScriptedMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
||||||
if (engine->hasUncaughtException()) {
|
if (engine->hasUncaughtException()) {
|
||||||
qDebug() << "Script error: " << engine->uncaughtException().toString();
|
qDebug() << "Script error: " << engine->uncaughtException().toString();
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptedMetavoxelGuide::setURL(const ParameterizedURL& url) {
|
void ScriptedMetavoxelGuide::setURL(const ParameterizedURL& url) {
|
||||||
|
|
|
@ -194,8 +194,24 @@ public:
|
||||||
class MetavoxelVisitor {
|
class MetavoxelVisitor {
|
||||||
public:
|
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,
|
MetavoxelVisitor(const QVector<AttributePointer>& inputs,
|
||||||
const QVector<AttributePointer>& outputs = QVector<AttributePointer>());
|
const QVector<AttributePointer>& outputs = QVector<AttributePointer>(),
|
||||||
|
const MetavoxelLOD& lod = MetavoxelLOD());
|
||||||
virtual ~MetavoxelVisitor();
|
virtual ~MetavoxelVisitor();
|
||||||
|
|
||||||
/// Returns a reference to the list of input attributes desired.
|
/// 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.
|
/// Returns a reference to the list of output attributes provided.
|
||||||
const QVector<AttributePointer>& getOutputs() const { return _outputs; }
|
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.
|
/// Prepares for a new tour of the metavoxel data.
|
||||||
virtual void prepare();
|
virtual void prepare();
|
||||||
|
|
||||||
/// Visits a metavoxel.
|
/// Visits a metavoxel.
|
||||||
/// \param info the metavoxel data
|
/// \param info the metavoxel data
|
||||||
/// \return if true, continue descending; if false, stop
|
/// \return the encoded order in which to traverse the children, zero to stop recursion, or -1 to short-circuit the tour
|
||||||
virtual bool visit(MetavoxelInfo& info) = 0;
|
virtual int visit(MetavoxelInfo& info) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
QVector<AttributePointer> _inputs;
|
QVector<AttributePointer> _inputs;
|
||||||
QVector<AttributePointer> _outputs;
|
QVector<AttributePointer> _outputs;
|
||||||
|
MetavoxelLOD _lod;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef QSharedPointer<MetavoxelVisitor> MetavoxelVisitorPointer;
|
typedef QSharedPointer<MetavoxelVisitor> MetavoxelVisitorPointer;
|
||||||
|
@ -226,13 +248,15 @@ public:
|
||||||
|
|
||||||
SpannerVisitor(const QVector<AttributePointer>& spannerInputs,
|
SpannerVisitor(const QVector<AttributePointer>& spannerInputs,
|
||||||
const QVector<AttributePointer>& inputs = QVector<AttributePointer>(),
|
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.
|
/// 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 void prepare();
|
||||||
virtual bool visit(MetavoxelInfo& info);
|
virtual int visit(MetavoxelInfo& info);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -246,7 +270,8 @@ class MetavoxelGuide : public SharedObject {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// Guides the specified visitor to the contained voxels.
|
/// 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.
|
/// Guides visitors through the explicit content of the system.
|
||||||
|
@ -257,7 +282,7 @@ public:
|
||||||
|
|
||||||
Q_INVOKABLE DefaultMetavoxelGuide();
|
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.
|
/// A temporary test guide that just makes the existing voxels throb with delight.
|
||||||
|
@ -269,7 +294,7 @@ public:
|
||||||
|
|
||||||
Q_INVOKABLE ThrobbingMetavoxelGuide();
|
Q_INVOKABLE ThrobbingMetavoxelGuide();
|
||||||
|
|
||||||
virtual void guide(MetavoxelVisitation& visitation);
|
virtual bool guide(MetavoxelVisitation& visitation);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -285,7 +310,7 @@ public:
|
||||||
|
|
||||||
Q_INVOKABLE ScriptedMetavoxelGuide();
|
Q_INVOKABLE ScriptedMetavoxelGuide();
|
||||||
|
|
||||||
virtual void guide(MetavoxelVisitation& visitation);
|
virtual bool guide(MetavoxelVisitation& visitation);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ public:
|
||||||
|
|
||||||
BoxSetEditVisitor(const BoxSetEdit& edit);
|
BoxSetEditVisitor(const BoxSetEdit& edit);
|
||||||
|
|
||||||
virtual bool visit(MetavoxelInfo& info);
|
virtual int visit(MetavoxelInfo& info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -36,26 +36,26 @@ BoxSetEditVisitor::BoxSetEditVisitor(const BoxSetEdit& edit) :
|
||||||
_edit(edit) {
|
_edit(edit) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BoxSetEditVisitor::visit(MetavoxelInfo& info) {
|
int BoxSetEditVisitor::visit(MetavoxelInfo& info) {
|
||||||
// find the intersection between volume and voxel
|
// find the intersection between volume and voxel
|
||||||
glm::vec3 minimum = glm::max(info.minimum, _edit.region.minimum);
|
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 maximum = glm::min(info.minimum + glm::vec3(info.size, info.size, info.size), _edit.region.maximum);
|
||||||
glm::vec3 size = maximum - minimum;
|
glm::vec3 size = maximum - minimum;
|
||||||
if (size.x <= 0.0f || size.y <= 0.0f || size.z <= 0.0f) {
|
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);
|
float volume = (size.x * size.y * size.z) / (info.size * info.size * info.size);
|
||||||
if (volume >= 1.0f) {
|
if (volume >= 1.0f) {
|
||||||
info.outputValues[0] = _edit.value;
|
info.outputValues[0] = _edit.value;
|
||||||
return false; // entirely contained
|
return STOP_RECURSION; // entirely contained
|
||||||
}
|
}
|
||||||
if (info.size <= _edit.granularity) {
|
if (info.size <= _edit.granularity) {
|
||||||
if (volume >= 0.5f) {
|
if (volume >= 0.5f) {
|
||||||
info.outputValues[0] = _edit.value;
|
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 {
|
void BoxSetEdit::apply(MetavoxelData& data) const {
|
||||||
|
@ -77,7 +77,7 @@ public:
|
||||||
|
|
||||||
GlobalSetEditVisitor(const GlobalSetEdit& edit);
|
GlobalSetEditVisitor(const GlobalSetEdit& edit);
|
||||||
|
|
||||||
virtual bool visit(MetavoxelInfo& info);
|
virtual int visit(MetavoxelInfo& info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -89,9 +89,9 @@ GlobalSetEditVisitor::GlobalSetEditVisitor(const GlobalSetEdit& edit) :
|
||||||
_edit(edit) {
|
_edit(edit) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GlobalSetEditVisitor::visit(MetavoxelInfo& info) {
|
int GlobalSetEditVisitor::visit(MetavoxelInfo& info) {
|
||||||
info.outputValues[0] = _edit.value;
|
info.outputValues[0] = _edit.value;
|
||||||
return false; // entirely contained
|
return STOP_RECURSION; // entirely contained
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalSetEdit::apply(MetavoxelData& data) const {
|
void GlobalSetEdit::apply(MetavoxelData& data) const {
|
||||||
|
|
Loading…
Reference in a new issue