void MetavoxelData::guide(MetavoxelVisitor& visitor) { // start with the root values/defaults (plus the guide attribute) const QVector<AttributePointer>& inputs = visitor.getInputs(); const QVector<AttributePointer>& outputs = visitor.getOutputs(); MetavoxelVisitation firstVisitation = { NULL, visitor, QVector<MetavoxelNode*>(inputs.size() + 1), QVector<MetavoxelNode*>(outputs.size()), { glm::vec3(_size, _size, _size) * -0.5f, _size, QVector<AttributeValue>(inputs.size() + 1), QVector<AttributeValue>(outputs.size()) } }; for (int i = 0; i < inputs.size(); i++) { MetavoxelNode* node = _roots.value(inputs.at(i)); firstVisitation.inputNodes[i] = node; firstVisitation.info.inputValues[i] = node ? node->getAttributeValue(inputs[i]) : inputs[i]; } AttributePointer guideAttribute = AttributeRegistry::getInstance()->getGuideAttribute(); MetavoxelNode* node = _roots.value(guideAttribute); firstVisitation.inputNodes.last() = node; firstVisitation.info.inputValues.last() = node ? node->getAttributeValue(guideAttribute) : guideAttribute; for (int i = 0; i < outputs.size(); i++) { MetavoxelNode* node = _roots.value(outputs.at(i)); firstVisitation.outputNodes[i] = node; } static_cast<MetavoxelGuide*>(firstVisitation.info.inputValues.last().getInlineValue< PolymorphicDataPointer>().data())->guide(firstVisitation); for (int i = 0; i < outputs.size(); i++) { AttributeValue& value = firstVisitation.info.outputValues[i]; if (!value.getAttribute()) { continue; } // replace the old node with the new MetavoxelNode*& node = _roots[value.getAttribute()]; if (node) { node->decrementReferenceCount(value.getAttribute()); } node = firstVisitation.outputNodes.at(i); if (node->isLeaf() && value.isDefault()) { // immediately remove the new node if redundant node->decrementReferenceCount(value.getAttribute()); _roots.remove(value.getAttribute()); } } }
void DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) { visitation.info.isLeaf = visitation.allInputNodesLeaves(); bool keepGoing = visitation.visitor.visit(visitation.info); for (int i = 0; i < visitation.outputNodes.size(); i++) { AttributeValue& value = visitation.info.outputValues[i]; if (!value.getAttribute()) { continue; } MetavoxelNode*& node = visitation.outputNodes[i]; if (node && node->isLeaf() && value.getAttribute()->equal(value.getValue(), node->getAttributeValue())) { // "set" to same value; disregard value = AttributeValue(); } else { node = new MetavoxelNode(value); } } if (!keepGoing) { return; } 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<AttributeValue>(visitation.outputNodes.size()) } }; for (int i = 0; i < MetavoxelNode::CHILD_COUNT; i++) { for (int j = 0; j < visitation.inputNodes.size(); j++) { MetavoxelNode* node = visitation.inputNodes.at(j); MetavoxelNode* child = node ? node->getChild(i) : 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; nextVisitation.outputNodes[j] = child; } nextVisitation.info.minimum = visitation.info.minimum + glm::vec3( (i & X_MAXIMUM_FLAG) ? nextVisitation.info.size : 0.0f, (i & Y_MAXIMUM_FLAG) ? nextVisitation.info.size : 0.0f, (i & Z_MAXIMUM_FLAG) ? nextVisitation.info.size : 0.0f); static_cast<MetavoxelGuide*>(nextVisitation.info.inputValues.last().getInlineValue< PolymorphicDataPointer>().data())->guide(nextVisitation); for (int j = 0; j < nextVisitation.outputNodes.size(); j++) { AttributeValue& value = nextVisitation.info.outputValues[j]; if (!value.getAttribute()) { continue; } // replace the child AttributeValue& parentValue = visitation.info.outputValues[j]; if (!parentValue.getAttribute()) { // shallow-copy the parent node on first change parentValue = value; MetavoxelNode*& node = visitation.outputNodes[j]; if (node) { node = new MetavoxelNode(value.getAttribute(), node); } else { // create leaf with inherited value node = new MetavoxelNode(visitation.getInheritedOutputValue(j)); } } MetavoxelNode* node = visitation.outputNodes.at(j); MetavoxelNode* child = node->getChild(i); if (child) { child->decrementReferenceCount(value.getAttribute()); } else { // 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(i, nextVisitation.outputNodes.at(j)); value = AttributeValue(); } } for (int i = 0; i < visitation.outputNodes.size(); i++) { AttributeValue& value = visitation.info.outputValues[i]; if (value.getAttribute()) { MetavoxelNode* node = visitation.outputNodes.at(i); node->mergeChildren(value.getAttribute()); value = node->getAttributeValue(value.getAttribute()); } } }