Working on allowing visitors to modify, as well as read, data.

This commit is contained in:
Andrzej Kapolka 2014-01-13 18:09:28 -08:00
parent 3734aa4fe1
commit c163b513d2
4 changed files with 82 additions and 56 deletions

View file

@ -35,11 +35,11 @@ function setNormal(vector) {
if (normalIndex != -1) { if (normalIndex != -1) {
var length = Math.sqrt(lengthSquared(vector[0], vector[1], vector[2])); var length = Math.sqrt(lengthSquared(vector[0], vector[1], vector[2]));
if (length == 0.0) { if (length == 0.0) {
info.attributeValues[normalIndex] = 0x007F00; info.inputValues[normalIndex] = 0x007F00;
} else { } else {
var scale = 127.0 / length; var scale = 127.0 / length;
info.attributeValues[normalIndex] = info.inputValues[normalIndex] =
(Math.floor(vector[0] * scale) & 0xFF) << 16 | (Math.floor(vector[0] * scale) & 0xFF) << 16 |
(Math.floor(vector[1] * scale) & 0xFF) << 8 | (Math.floor(vector[1] * scale) & 0xFF) << 8 |
Math.floor(vector[2] * scale) & 0xFF; Math.floor(vector[2] * scale) & 0xFF;
@ -61,7 +61,7 @@ function guide(minimum, size, depth) {
maximum[2] <= sphereCenter[2] - sphereRadius) { maximum[2] <= sphereCenter[2] - sphereRadius) {
info.isLeaf = true; info.isLeaf = true;
if (colorIndex != -1) { if (colorIndex != -1) {
info.attributeValues[colorIndex] = 0x0; info.inputValues[colorIndex] = 0x0;
} }
visitor.visit(info); visitor.visit(info);
return; return;
@ -110,7 +110,7 @@ function guide(minimum, size, depth) {
if (inside == 8) { if (inside == 8) {
info.isLeaf = true; info.isLeaf = true;
if (colorIndex != -1) { if (colorIndex != -1) {
info.attributeValues[colorIndex] = sphereColor; info.inputValues[colorIndex] = sphereColor;
} }
setNormal(vector); setNormal(vector);
visitor.visit(info); visitor.visit(info);
@ -122,13 +122,13 @@ function guide(minimum, size, depth) {
info.isLeaf = true; info.isLeaf = true;
if (inside >= 3) { if (inside >= 3) {
if (colorIndex != -1) { if (colorIndex != -1) {
info.attributeValues[colorIndex] = sphereColor; info.inputValues[colorIndex] = sphereColor;
} }
setNormal(vector); setNormal(vector);
} else { } else {
if (colorIndex != -1) { if (colorIndex != -1) {
info.attributeValues[colorIndex] = 0x0; info.inputValues[colorIndex] = 0x0;
} }
} }
visitor.visit(info); visitor.visit(info);
@ -152,11 +152,11 @@ function guide(minimum, size, depth) {
} }
(function(visitation) { (function(visitation) {
var attributes = visitation.visitor.getAttributes(); var inputs = visitation.visitor.getInputs();
colorIndex = strictIndexOf(attributes, AttributeRegistry.colorAttribute); colorIndex = strictIndexOf(inputs, AttributeRegistry.colorAttribute);
normalIndex = strictIndexOf(attributes, AttributeRegistry.normalAttribute); normalIndex = strictIndexOf(inputs, AttributeRegistry.normalAttribute);
visitor = visitation.visitor; visitor = visitation.visitor;
info = { attributeValues: new Array(attributes.length) }; info = { inputValues: new Array(inputs.length) };
// have the sphere orbit the center and pulse in size // have the sphere orbit the center and pulse in size
var time = new Date().getTime(); var time = new Date().getTime();

View file

@ -157,7 +157,8 @@ void MetavoxelSystem::receivedData(const QByteArray& data, const HifiSockAddr& s
MetavoxelSystem::PointVisitor::PointVisitor(QVector<Point>& points) : MetavoxelSystem::PointVisitor::PointVisitor(QVector<Point>& points) :
MetavoxelVisitor(QVector<AttributePointer>() << MetavoxelVisitor(QVector<AttributePointer>() <<
AttributeRegistry::getInstance()->getColorAttribute() << AttributeRegistry::getInstance()->getColorAttribute() <<
AttributeRegistry::getInstance()->getNormalAttribute()), AttributeRegistry::getInstance()->getNormalAttribute(),
QVector<AttributePointer>()),
_points(points) { _points(points) {
} }
@ -165,8 +166,8 @@ bool MetavoxelSystem::PointVisitor::visit(const MetavoxelInfo& info) {
if (!info.isLeaf) { if (!info.isLeaf) {
return true; return true;
} }
QRgb color = info.attributeValues.at(0).getInlineValue<QRgb>(); QRgb color = info.inputValues.at(0).getInlineValue<QRgb>();
QRgb normal = info.attributeValues.at(1).getInlineValue<QRgb>(); QRgb normal = info.inputValues.at(1).getInlineValue<QRgb>();
int alpha = qAlpha(color); int alpha = qAlpha(color);
if (alpha > 0) { if (alpha > 0) {
Point point = { glm::vec4(info.minimum + glm::vec3(info.size, info.size, info.size) * 0.5f, info.size), Point point = { glm::vec4(info.minimum + glm::vec3(info.size, info.size, info.size) * 0.5f, info.size),

View file

@ -32,19 +32,20 @@ MetavoxelData& MetavoxelData::operator=(const MetavoxelData& other) {
void MetavoxelData::guide(MetavoxelVisitor& visitor) { void MetavoxelData::guide(MetavoxelVisitor& visitor) {
// start with the root values/defaults (plus the guide attribute) // start with the root values/defaults (plus the guide attribute)
const float TOP_LEVEL_SIZE = 1.0f; const float TOP_LEVEL_SIZE = 1.0f;
const QVector<AttributePointer>& attributes = visitor.getAttributes(); const QVector<AttributePointer>& inputs = visitor.getInputs();
MetavoxelVisitation firstVisitation = { visitor, QVector<MetavoxelNode*>(attributes.size() + 1), const QVector<AttributePointer>& outputs = visitor.getOutputs();
{ glm::vec3(), TOP_LEVEL_SIZE, QVector<AttributeValue>(attributes.size() + 1) } }; MetavoxelVisitation firstVisitation = { visitor, QVector<MetavoxelNode*>(inputs.size() + 1),
for (int i = 0; i < attributes.size(); i++) { { glm::vec3(), TOP_LEVEL_SIZE, QVector<AttributeValue>(inputs.size() + 1), QVector<AttributeValue>(outputs.size()) } };
MetavoxelNode* node = _roots.value(attributes[i]); for (int i = 0; i < inputs.size(); i++) {
MetavoxelNode* node = _roots.value(inputs[i]);
firstVisitation.nodes[i] = node; firstVisitation.nodes[i] = node;
firstVisitation.info.attributeValues[i] = node ? node->getAttributeValue(attributes[i]) : attributes[i]; firstVisitation.info.inputValues[i] = node ? node->getAttributeValue(inputs[i]) : inputs[i];
} }
AttributePointer guideAttribute = AttributeRegistry::getInstance()->getGuideAttribute(); AttributePointer guideAttribute = AttributeRegistry::getInstance()->getGuideAttribute();
MetavoxelNode* node = _roots.value(guideAttribute); MetavoxelNode* node = _roots.value(guideAttribute);
firstVisitation.nodes.last() = node; firstVisitation.nodes.last() = node;
firstVisitation.info.attributeValues.last() = node ? node->getAttributeValue(guideAttribute) : guideAttribute; firstVisitation.info.inputValues.last() = node ? node->getAttributeValue(guideAttribute) : guideAttribute;
static_cast<MetavoxelGuide*>(firstVisitation.info.attributeValues.last().getInlineValue< static_cast<MetavoxelGuide*>(firstVisitation.info.inputValues.last().getInlineValue<
PolymorphicDataPointer>().data())->guide(firstVisitation); PolymorphicDataPointer>().data())->guide(firstVisitation);
} }
@ -369,6 +370,11 @@ MetavoxelPath& MetavoxelPath::operator+=(int element) {
return *this; return *this;
} }
MetavoxelVisitor::MetavoxelVisitor(const QVector<AttributePointer>& inputs, const QVector<AttributePointer>& outputs) :
_inputs(inputs),
_outputs(outputs) {
}
PolymorphicData* DefaultMetavoxelGuide::clone() const { PolymorphicData* DefaultMetavoxelGuide::clone() const {
return new DefaultMetavoxelGuide(); return new DefaultMetavoxelGuide();
} }
@ -379,7 +385,7 @@ const int Z_MAXIMUM_FLAG = 4;
void DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) { void DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
visitation.info.isLeaf = visitation.allNodesLeaves(); visitation.info.isLeaf = visitation.allNodesLeaves();
if (!visitation.visitor.visit(visitation.info) || visitation.info.isLeaf) { if (!visitation.visitor.visit(visitation.info)) {
return; return;
} }
MetavoxelVisitation nextVisitation = { visitation.visitor, QVector<MetavoxelNode*>(visitation.nodes.size()), MetavoxelVisitation nextVisitation = { visitation.visitor, QVector<MetavoxelNode*>(visitation.nodes.size()),
@ -388,32 +394,40 @@ void DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
for (int j = 0; j < visitation.nodes.size(); j++) { for (int j = 0; j < visitation.nodes.size(); j++) {
MetavoxelNode* node = visitation.nodes.at(j); MetavoxelNode* node = visitation.nodes.at(j);
MetavoxelNode* child = node ? node->getChild(i) : NULL; MetavoxelNode* child = node ? node->getChild(i) : NULL;
nextVisitation.info.attributeValues[j] = ((nextVisitation.nodes[j] = child)) ? nextVisitation.info.inputValues[j] = ((nextVisitation.nodes[j] = child)) ?
child->getAttributeValue(visitation.info.attributeValues[j].getAttribute()) : child->getAttributeValue(visitation.info.inputValues[j].getAttribute()) :
visitation.info.attributeValues[j]; visitation.info.inputValues[j];
} }
nextVisitation.info.minimum = visitation.info.minimum + glm::vec3( nextVisitation.info.minimum = visitation.info.minimum + glm::vec3(
(i & X_MAXIMUM_FLAG) ? nextVisitation.info.size : 0.0f, (i & X_MAXIMUM_FLAG) ? nextVisitation.info.size : 0.0f,
(i & Y_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); (i & Z_MAXIMUM_FLAG) ? nextVisitation.info.size : 0.0f);
static_cast<MetavoxelGuide*>(nextVisitation.info.attributeValues.last().getInlineValue< static_cast<MetavoxelGuide*>(nextVisitation.info.inputValues.last().getInlineValue<
PolymorphicDataPointer>().data())->guide(nextVisitation); PolymorphicDataPointer>().data())->guide(nextVisitation);
} }
} }
QScriptValue ScriptedMetavoxelGuide::getAttributes(QScriptContext* context, QScriptEngine* engine) { static QScriptValue getAttributes(QScriptEngine* engine, ScriptedMetavoxelGuide* guide,
ScriptedMetavoxelGuide* guide = static_cast<ScriptedMetavoxelGuide*>(context->callee().data().toVariant().value<void*>()); const QVector<AttributePointer>& attributes) {
const QVector<AttributePointer>& attributes = guide->_visitation->visitor.getAttributes();
QScriptValue attributesValue = engine->newArray(attributes.size()); QScriptValue attributesValue = engine->newArray(attributes.size());
for (int i = 0; i < attributes.size(); i++) { for (int i = 0; i < attributes.size(); i++) {
attributesValue.setProperty(i, engine->newQObject(attributes.at(i).data(), QScriptEngine::QtOwnership, attributesValue.setProperty(i, engine->newQObject(attributes.at(i).data(), QScriptEngine::QtOwnership,
QScriptEngine::PreferExistingWrapperObject)); QScriptEngine::PreferExistingWrapperObject));
} }
return attributesValue; return attributesValue;
} }
QScriptValue ScriptedMetavoxelGuide::getInputs(QScriptContext* context, QScriptEngine* engine) {
ScriptedMetavoxelGuide* guide = static_cast<ScriptedMetavoxelGuide*>(context->callee().data().toVariant().value<void*>());
return getAttributes(engine, guide, guide->_visitation->visitor.getInputs());
}
QScriptValue ScriptedMetavoxelGuide::getOutputs(QScriptContext* context, QScriptEngine* engine) {
ScriptedMetavoxelGuide* guide = static_cast<ScriptedMetavoxelGuide*>(context->callee().data().toVariant().value<void*>());
return getAttributes(engine, guide, guide->_visitation->visitor.getOutputs());
}
QScriptValue ScriptedMetavoxelGuide::visit(QScriptContext* context, QScriptEngine* engine) { QScriptValue ScriptedMetavoxelGuide::visit(QScriptContext* context, QScriptEngine* engine) {
ScriptedMetavoxelGuide* guide = static_cast<ScriptedMetavoxelGuide*>(context->callee().data().toVariant().value<void*>()); ScriptedMetavoxelGuide* guide = static_cast<ScriptedMetavoxelGuide*>(context->callee().data().toVariant().value<void*>());
@ -422,26 +436,26 @@ QScriptValue ScriptedMetavoxelGuide::visit(QScriptContext* context, QScriptEngin
QScriptValue minimum = infoValue.property(guide->_minimumHandle); QScriptValue minimum = infoValue.property(guide->_minimumHandle);
MetavoxelInfo info = { MetavoxelInfo info = {
glm::vec3(minimum.property(0).toNumber(), minimum.property(1).toNumber(), minimum.property(2).toNumber()), glm::vec3(minimum.property(0).toNumber(), minimum.property(1).toNumber(), minimum.property(2).toNumber()),
infoValue.property(guide->_sizeHandle).toNumber(), guide->_visitation->info.attributeValues, infoValue.property(guide->_sizeHandle).toNumber(), guide->_visitation->info.inputValues,
infoValue.property(guide->_isLeafHandle).toBool() }; guide->_visitation->info.outputValues, infoValue.property(guide->_isLeafHandle).toBool() };
// extract and convert the values provided by the script // extract and convert the values provided by the script
QScriptValue attributeValues = infoValue.property(guide->_attributeValuesHandle); QScriptValue inputValues = infoValue.property(guide->_inputValuesHandle);
const QVector<AttributePointer>& attributes = guide->_visitation->visitor.getAttributes(); const QVector<AttributePointer>& inputs = guide->_visitation->visitor.getInputs();
for (int i = 0; i < attributes.size(); i++) { for (int i = 0; i < inputs.size(); i++) {
QScriptValue attributeValue = attributeValues.property(i); QScriptValue attributeValue = inputValues.property(i);
if (attributeValue.isValid()) { if (attributeValue.isValid()) {
info.attributeValues[i] = AttributeValue(attributes.at(i), info.inputValues[i] = AttributeValue(inputs.at(i),
attributes.at(i)->createFromScript(attributeValue, engine)); inputs.at(i)->createFromScript(attributeValue, engine));
} }
} }
QScriptValue result = guide->_visitation->visitor.visit(info); QScriptValue result = guide->_visitation->visitor.visit(info);
// destroy any created values // destroy any created values
for (int i = 0; i < attributes.size(); i++) { for (int i = 0; i < inputs.size(); i++) {
if (attributeValues.property(i).isValid()) { if (inputValues.property(i).isValid()) {
info.attributeValues[i].getAttribute()->destroy(info.attributeValues[i].getValue()); info.inputValues[i].getAttribute()->destroy(info.inputValues[i].getValue());
} }
} }
@ -452,16 +466,19 @@ ScriptedMetavoxelGuide::ScriptedMetavoxelGuide(const QScriptValue& guideFunction
_guideFunction(guideFunction), _guideFunction(guideFunction),
_minimumHandle(guideFunction.engine()->toStringHandle("minimum")), _minimumHandle(guideFunction.engine()->toStringHandle("minimum")),
_sizeHandle(guideFunction.engine()->toStringHandle("size")), _sizeHandle(guideFunction.engine()->toStringHandle("size")),
_attributeValuesHandle(guideFunction.engine()->toStringHandle("attributeValues")), _inputValuesHandle(guideFunction.engine()->toStringHandle("inputValues")),
_outputValuesHandle(guideFunction.engine()->toStringHandle("outputValues")),
_isLeafHandle(guideFunction.engine()->toStringHandle("isLeaf")), _isLeafHandle(guideFunction.engine()->toStringHandle("isLeaf")),
_getAttributesFunction(guideFunction.engine()->newFunction(getAttributes, 0)), _getInputsFunction(guideFunction.engine()->newFunction(getInputs, 0)),
_getOutputsFunction(guideFunction.engine()->newFunction(getOutputs, 0)),
_visitFunction(guideFunction.engine()->newFunction(visit, 1)), _visitFunction(guideFunction.engine()->newFunction(visit, 1)),
_info(guideFunction.engine()->newObject()), _info(guideFunction.engine()->newObject()),
_minimum(guideFunction.engine()->newArray(3)) { _minimum(guideFunction.engine()->newArray(3)) {
_arguments.append(guideFunction.engine()->newObject()); _arguments.append(guideFunction.engine()->newObject());
QScriptValue visitor = guideFunction.engine()->newObject(); QScriptValue visitor = guideFunction.engine()->newObject();
visitor.setProperty("getAttributes", _getAttributesFunction); visitor.setProperty("getInputs", _getInputsFunction);
visitor.setProperty("getOutputs", _getOutputsFunction);
visitor.setProperty("visit", _visitFunction); visitor.setProperty("visit", _visitFunction);
_arguments[0].setProperty("visitor", visitor); _arguments[0].setProperty("visitor", visitor);
_arguments[0].setProperty("info", _info); _arguments[0].setProperty("info", _info);
@ -474,7 +491,7 @@ PolymorphicData* ScriptedMetavoxelGuide::clone() const {
void ScriptedMetavoxelGuide::guide(MetavoxelVisitation& visitation) { void ScriptedMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
QScriptValue data = _guideFunction.engine()->newVariant(QVariant::fromValue<void*>(this)); QScriptValue data = _guideFunction.engine()->newVariant(QVariant::fromValue<void*>(this));
_getAttributesFunction.setData(data); _getInputsFunction.setData(data);
_visitFunction.setData(data); _visitFunction.setData(data);
_minimum.setProperty(0, visitation.info.minimum.x); _minimum.setProperty(0, visitation.info.minimum.x);
_minimum.setProperty(1, visitation.info.minimum.y); _minimum.setProperty(1, visitation.info.minimum.y);

View file

@ -139,7 +139,8 @@ public:
glm::vec3 minimum; ///< the minimum extent of the area covered by the voxel glm::vec3 minimum; ///< the minimum extent of the area covered by the voxel
float size; ///< the size of the voxel in all dimensions float size; ///< the size of the voxel in all dimensions
QVector<AttributeValue> attributeValues; QVector<AttributeValue> inputValues;
QVector<AttributeValue> outputValues;
bool isLeaf; bool isLeaf;
}; };
@ -147,19 +148,23 @@ public:
class MetavoxelVisitor { class MetavoxelVisitor {
public: public:
MetavoxelVisitor(const QVector<AttributePointer>& attributes) : _attributes(attributes) { } MetavoxelVisitor(const QVector<AttributePointer>& inputs, const QVector<AttributePointer>& outputs);
/// Returns a reference to the list of attributes desired. /// Returns a reference to the list of input attributes desired.
const QVector<AttributePointer>& getAttributes() const { return _attributes; } const QVector<AttributePointer>& getInputs() const { return _inputs; }
/// Returns a reference to the list of output attributes provided.
const QVector<AttributePointer>& getOutputs() const { return _outputs; }
/// Visits a metavoxel. /// Visits a metavoxel.
/// \param info the metavoxel ata /// \param info the metavoxel data
/// \param if true, continue descending; if false, stop /// \return if true, continue descending; if false, stop
virtual bool visit(const MetavoxelInfo& info) = 0; virtual bool visit(const MetavoxelInfo& info) = 0;
protected: protected:
QVector<AttributePointer> _attributes; QVector<AttributePointer> _inputs;
QVector<AttributePointer> _outputs;
}; };
/// Interface for objects that guide metavoxel visitors. /// Interface for objects that guide metavoxel visitors.
@ -191,16 +196,19 @@ public:
private: private:
static QScriptValue getAttributes(QScriptContext* context, QScriptEngine* engine); static QScriptValue getInputs(QScriptContext* context, QScriptEngine* engine);
static QScriptValue getOutputs(QScriptContext* context, QScriptEngine* engine);
static QScriptValue visit(QScriptContext* context, QScriptEngine* engine); static QScriptValue visit(QScriptContext* context, QScriptEngine* engine);
QScriptValue _guideFunction; QScriptValue _guideFunction;
QScriptString _minimumHandle; QScriptString _minimumHandle;
QScriptString _sizeHandle; QScriptString _sizeHandle;
QScriptString _attributeValuesHandle; QScriptString _inputValuesHandle;
QScriptString _outputValuesHandle;
QScriptString _isLeafHandle; QScriptString _isLeafHandle;
QScriptValueList _arguments; QScriptValueList _arguments;
QScriptValue _getAttributesFunction; QScriptValue _getInputsFunction;
QScriptValue _getOutputsFunction;
QScriptValue _visitFunction; QScriptValue _visitFunction;
QScriptValue _info; QScriptValue _info;
QScriptValue _minimum; QScriptValue _minimum;