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) {
var length = Math.sqrt(lengthSquared(vector[0], vector[1], vector[2]));
if (length == 0.0) {
info.attributeValues[normalIndex] = 0x007F00;
info.inputValues[normalIndex] = 0x007F00;
} else {
var scale = 127.0 / length;
info.attributeValues[normalIndex] =
info.inputValues[normalIndex] =
(Math.floor(vector[0] * scale) & 0xFF) << 16 |
(Math.floor(vector[1] * scale) & 0xFF) << 8 |
Math.floor(vector[2] * scale) & 0xFF;
@ -61,7 +61,7 @@ function guide(minimum, size, depth) {
maximum[2] <= sphereCenter[2] - sphereRadius) {
info.isLeaf = true;
if (colorIndex != -1) {
info.attributeValues[colorIndex] = 0x0;
info.inputValues[colorIndex] = 0x0;
}
visitor.visit(info);
return;
@ -110,7 +110,7 @@ function guide(minimum, size, depth) {
if (inside == 8) {
info.isLeaf = true;
if (colorIndex != -1) {
info.attributeValues[colorIndex] = sphereColor;
info.inputValues[colorIndex] = sphereColor;
}
setNormal(vector);
visitor.visit(info);
@ -122,13 +122,13 @@ function guide(minimum, size, depth) {
info.isLeaf = true;
if (inside >= 3) {
if (colorIndex != -1) {
info.attributeValues[colorIndex] = sphereColor;
info.inputValues[colorIndex] = sphereColor;
}
setNormal(vector);
} else {
if (colorIndex != -1) {
info.attributeValues[colorIndex] = 0x0;
info.inputValues[colorIndex] = 0x0;
}
}
visitor.visit(info);
@ -152,11 +152,11 @@ function guide(minimum, size, depth) {
}
(function(visitation) {
var attributes = visitation.visitor.getAttributes();
colorIndex = strictIndexOf(attributes, AttributeRegistry.colorAttribute);
normalIndex = strictIndexOf(attributes, AttributeRegistry.normalAttribute);
var inputs = visitation.visitor.getInputs();
colorIndex = strictIndexOf(inputs, AttributeRegistry.colorAttribute);
normalIndex = strictIndexOf(inputs, AttributeRegistry.normalAttribute);
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
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) :
MetavoxelVisitor(QVector<AttributePointer>() <<
AttributeRegistry::getInstance()->getColorAttribute() <<
AttributeRegistry::getInstance()->getNormalAttribute()),
AttributeRegistry::getInstance()->getNormalAttribute(),
QVector<AttributePointer>()),
_points(points) {
}
@ -165,8 +166,8 @@ bool MetavoxelSystem::PointVisitor::visit(const MetavoxelInfo& info) {
if (!info.isLeaf) {
return true;
}
QRgb color = info.attributeValues.at(0).getInlineValue<QRgb>();
QRgb normal = info.attributeValues.at(1).getInlineValue<QRgb>();
QRgb color = info.inputValues.at(0).getInlineValue<QRgb>();
QRgb normal = info.inputValues.at(1).getInlineValue<QRgb>();
int alpha = qAlpha(color);
if (alpha > 0) {
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) {
// start with the root values/defaults (plus the guide attribute)
const float TOP_LEVEL_SIZE = 1.0f;
const QVector<AttributePointer>& attributes = visitor.getAttributes();
MetavoxelVisitation firstVisitation = { visitor, QVector<MetavoxelNode*>(attributes.size() + 1),
{ glm::vec3(), TOP_LEVEL_SIZE, QVector<AttributeValue>(attributes.size() + 1) } };
for (int i = 0; i < attributes.size(); i++) {
MetavoxelNode* node = _roots.value(attributes[i]);
const QVector<AttributePointer>& inputs = visitor.getInputs();
const QVector<AttributePointer>& outputs = visitor.getOutputs();
MetavoxelVisitation firstVisitation = { visitor, QVector<MetavoxelNode*>(inputs.size() + 1),
{ glm::vec3(), TOP_LEVEL_SIZE, QVector<AttributeValue>(inputs.size() + 1), QVector<AttributeValue>(outputs.size()) } };
for (int i = 0; i < inputs.size(); i++) {
MetavoxelNode* node = _roots.value(inputs[i]);
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();
MetavoxelNode* node = _roots.value(guideAttribute);
firstVisitation.nodes.last() = node;
firstVisitation.info.attributeValues.last() = node ? node->getAttributeValue(guideAttribute) : guideAttribute;
static_cast<MetavoxelGuide*>(firstVisitation.info.attributeValues.last().getInlineValue<
firstVisitation.info.inputValues.last() = node ? node->getAttributeValue(guideAttribute) : guideAttribute;
static_cast<MetavoxelGuide*>(firstVisitation.info.inputValues.last().getInlineValue<
PolymorphicDataPointer>().data())->guide(firstVisitation);
}
@ -369,6 +370,11 @@ MetavoxelPath& MetavoxelPath::operator+=(int element) {
return *this;
}
MetavoxelVisitor::MetavoxelVisitor(const QVector<AttributePointer>& inputs, const QVector<AttributePointer>& outputs) :
_inputs(inputs),
_outputs(outputs) {
}
PolymorphicData* DefaultMetavoxelGuide::clone() const {
return new DefaultMetavoxelGuide();
}
@ -379,7 +385,7 @@ const int Z_MAXIMUM_FLAG = 4;
void DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
visitation.info.isLeaf = visitation.allNodesLeaves();
if (!visitation.visitor.visit(visitation.info) || visitation.info.isLeaf) {
if (!visitation.visitor.visit(visitation.info)) {
return;
}
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++) {
MetavoxelNode* node = visitation.nodes.at(j);
MetavoxelNode* child = node ? node->getChild(i) : NULL;
nextVisitation.info.attributeValues[j] = ((nextVisitation.nodes[j] = child)) ?
child->getAttributeValue(visitation.info.attributeValues[j].getAttribute()) :
visitation.info.attributeValues[j];
nextVisitation.info.inputValues[j] = ((nextVisitation.nodes[j] = child)) ?
child->getAttributeValue(visitation.info.inputValues[j].getAttribute()) :
visitation.info.inputValues[j];
}
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.attributeValues.last().getInlineValue<
static_cast<MetavoxelGuide*>(nextVisitation.info.inputValues.last().getInlineValue<
PolymorphicDataPointer>().data())->guide(nextVisitation);
}
}
QScriptValue ScriptedMetavoxelGuide::getAttributes(QScriptContext* context, QScriptEngine* engine) {
ScriptedMetavoxelGuide* guide = static_cast<ScriptedMetavoxelGuide*>(context->callee().data().toVariant().value<void*>());
static QScriptValue getAttributes(QScriptEngine* engine, ScriptedMetavoxelGuide* guide,
const QVector<AttributePointer>& attributes) {
const QVector<AttributePointer>& attributes = guide->_visitation->visitor.getAttributes();
QScriptValue attributesValue = engine->newArray(attributes.size());
for (int i = 0; i < attributes.size(); i++) {
attributesValue.setProperty(i, engine->newQObject(attributes.at(i).data(), QScriptEngine::QtOwnership,
QScriptEngine::PreferExistingWrapperObject));
}
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) {
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);
MetavoxelInfo info = {
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->_isLeafHandle).toBool() };
infoValue.property(guide->_sizeHandle).toNumber(), guide->_visitation->info.inputValues,
guide->_visitation->info.outputValues, infoValue.property(guide->_isLeafHandle).toBool() };
// extract and convert the values provided by the script
QScriptValue attributeValues = infoValue.property(guide->_attributeValuesHandle);
const QVector<AttributePointer>& attributes = guide->_visitation->visitor.getAttributes();
for (int i = 0; i < attributes.size(); i++) {
QScriptValue attributeValue = attributeValues.property(i);
QScriptValue inputValues = infoValue.property(guide->_inputValuesHandle);
const QVector<AttributePointer>& inputs = guide->_visitation->visitor.getInputs();
for (int i = 0; i < inputs.size(); i++) {
QScriptValue attributeValue = inputValues.property(i);
if (attributeValue.isValid()) {
info.attributeValues[i] = AttributeValue(attributes.at(i),
attributes.at(i)->createFromScript(attributeValue, engine));
info.inputValues[i] = AttributeValue(inputs.at(i),
inputs.at(i)->createFromScript(attributeValue, engine));
}
}
QScriptValue result = guide->_visitation->visitor.visit(info);
// destroy any created values
for (int i = 0; i < attributes.size(); i++) {
if (attributeValues.property(i).isValid()) {
info.attributeValues[i].getAttribute()->destroy(info.attributeValues[i].getValue());
for (int i = 0; i < inputs.size(); i++) {
if (inputValues.property(i).isValid()) {
info.inputValues[i].getAttribute()->destroy(info.inputValues[i].getValue());
}
}
@ -452,16 +466,19 @@ ScriptedMetavoxelGuide::ScriptedMetavoxelGuide(const QScriptValue& guideFunction
_guideFunction(guideFunction),
_minimumHandle(guideFunction.engine()->toStringHandle("minimum")),
_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")),
_getAttributesFunction(guideFunction.engine()->newFunction(getAttributes, 0)),
_getInputsFunction(guideFunction.engine()->newFunction(getInputs, 0)),
_getOutputsFunction(guideFunction.engine()->newFunction(getOutputs, 0)),
_visitFunction(guideFunction.engine()->newFunction(visit, 1)),
_info(guideFunction.engine()->newObject()),
_minimum(guideFunction.engine()->newArray(3)) {
_arguments.append(guideFunction.engine()->newObject());
QScriptValue visitor = guideFunction.engine()->newObject();
visitor.setProperty("getAttributes", _getAttributesFunction);
visitor.setProperty("getInputs", _getInputsFunction);
visitor.setProperty("getOutputs", _getOutputsFunction);
visitor.setProperty("visit", _visitFunction);
_arguments[0].setProperty("visitor", visitor);
_arguments[0].setProperty("info", _info);
@ -474,7 +491,7 @@ PolymorphicData* ScriptedMetavoxelGuide::clone() const {
void ScriptedMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
QScriptValue data = _guideFunction.engine()->newVariant(QVariant::fromValue<void*>(this));
_getAttributesFunction.setData(data);
_getInputsFunction.setData(data);
_visitFunction.setData(data);
_minimum.setProperty(0, visitation.info.minimum.x);
_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
float size; ///< the size of the voxel in all dimensions
QVector<AttributeValue> attributeValues;
QVector<AttributeValue> inputValues;
QVector<AttributeValue> outputValues;
bool isLeaf;
};
@ -147,19 +148,23 @@ public:
class MetavoxelVisitor {
public:
MetavoxelVisitor(const QVector<AttributePointer>& attributes) : _attributes(attributes) { }
/// Returns a reference to the list of attributes desired.
const QVector<AttributePointer>& getAttributes() const { return _attributes; }
MetavoxelVisitor(const QVector<AttributePointer>& inputs, const QVector<AttributePointer>& outputs);
/// Returns a reference to the list of input attributes desired.
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.
/// \param info the metavoxel ata
/// \param if true, continue descending; if false, stop
/// \param info the metavoxel data
/// \return if true, continue descending; if false, stop
virtual bool visit(const MetavoxelInfo& info) = 0;
protected:
QVector<AttributePointer> _attributes;
QVector<AttributePointer> _inputs;
QVector<AttributePointer> _outputs;
};
/// Interface for objects that guide metavoxel visitors.
@ -191,16 +196,19 @@ public:
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);
QScriptValue _guideFunction;
QScriptString _minimumHandle;
QScriptString _sizeHandle;
QScriptString _attributeValuesHandle;
QScriptString _inputValuesHandle;
QScriptString _outputValuesHandle;
QScriptString _isLeafHandle;
QScriptValueList _arguments;
QScriptValue _getAttributesFunction;
QScriptValue _getInputsFunction;
QScriptValue _getOutputsFunction;
QScriptValue _visitFunction;
QScriptValue _info;
QScriptValue _minimum;