mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 06:44:06 +02:00
More progress on generic attributes, metavoxel node management.
This commit is contained in:
parent
c423205709
commit
6ba750a963
8 changed files with 354 additions and 45 deletions
|
@ -1800,6 +1800,8 @@ void Application::init() {
|
|||
_voxels.setDisableFastVoxelPipeline(false);
|
||||
_voxels.init();
|
||||
|
||||
_metavoxels.init();
|
||||
|
||||
_palette.init(_glWidget->width(), _glWidget->height());
|
||||
_palette.addAction(Menu::getInstance()->getActionForOption(MenuOption::VoxelAddMode), 0, 0);
|
||||
_palette.addAction(Menu::getInstance()->getActionForOption(MenuOption::VoxelDeleteMode), 0, 1);
|
||||
|
|
|
@ -55,9 +55,10 @@
|
|||
#include "renderer/AmbientOcclusionEffect.h"
|
||||
#include "renderer/GeometryCache.h"
|
||||
#include "renderer/GlowEffect.h"
|
||||
#include "renderer/VoxelShader.h"
|
||||
#include "renderer/MetavoxelSystem.h"
|
||||
#include "renderer/PointShader.h"
|
||||
#include "renderer/TextureCache.h"
|
||||
#include "renderer/VoxelShader.h"
|
||||
#include "ui/BandwidthDialog.h"
|
||||
#include "ui/ChatEntry.h"
|
||||
#include "ui/VoxelStatsDialog.h"
|
||||
|
@ -345,6 +346,8 @@ private:
|
|||
QByteArray _voxelsFilename;
|
||||
bool _wantToKillLocalVoxels;
|
||||
|
||||
MetavoxelSystem _metavoxels;
|
||||
|
||||
ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc.
|
||||
|
||||
Oscilloscope _audioScope;
|
||||
|
|
16
interface/src/renderer/MetavoxelSystem.cpp
Normal file
16
interface/src/renderer/MetavoxelSystem.cpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
//
|
||||
// MetavoxelSystem.cpp
|
||||
// interface
|
||||
//
|
||||
// Created by Andrzej Kapolka on 12/10/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include <QtDebug>
|
||||
|
||||
#include "MetavoxelSystem.h"
|
||||
|
||||
void MetavoxelSystem::init() {
|
||||
qDebug() << "Howdy hello\n";
|
||||
}
|
||||
|
25
interface/src/renderer/MetavoxelSystem.h
Normal file
25
interface/src/renderer/MetavoxelSystem.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// MetavoxelSystem.h
|
||||
// interface
|
||||
//
|
||||
// Created by Andrzej Kapolka on 12/10/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __interface__MetavoxelSystem__
|
||||
#define __interface__MetavoxelSystem__
|
||||
|
||||
#include <MetavoxelData.h>
|
||||
|
||||
/// Renders a metavoxel tree.
|
||||
class MetavoxelSystem {
|
||||
public:
|
||||
|
||||
void init();
|
||||
|
||||
private:
|
||||
|
||||
MetavoxelData _data;
|
||||
};
|
||||
|
||||
#endif /* defined(__interface__MetavoxelSystem__) */
|
|
@ -10,22 +10,68 @@
|
|||
|
||||
AttributeRegistry AttributeRegistry::_instance;
|
||||
|
||||
AttributeRegistry::AttributeRegistry() : _lastAttributeID(0) {
|
||||
AttributeRegistry::AttributeRegistry() {
|
||||
registerAttribute(AttributePointer(new InlineAttribute<float, 32>("blerp")));
|
||||
}
|
||||
|
||||
AttributeID AttributeRegistry::getAttributeID(const QString& name) {
|
||||
AttributeID& id = _attributeIDs[name];
|
||||
if (id == 0) {
|
||||
id = ++_lastAttributeID;
|
||||
_attributes.insert(id, Attribute(id, name));
|
||||
AttributePointer AttributeRegistry::registerAttribute(AttributePointer attribute) {
|
||||
AttributePointer& pointer = _attributes[attribute->getName()];
|
||||
if (!pointer) {
|
||||
pointer = attribute;
|
||||
}
|
||||
return id;
|
||||
return pointer;
|
||||
}
|
||||
|
||||
Attribute AttributeRegistry::getAttribute(AttributeID id) const {
|
||||
return _attributes.value(id);
|
||||
}
|
||||
|
||||
Attribute::Attribute(AttributeID id, const QString& name) :
|
||||
_id(id), _name(name) {
|
||||
AttributeValue::AttributeValue(const AttributePointer& attribute, void* const* value) :
|
||||
_attribute(attribute) {
|
||||
|
||||
if (_attribute) {
|
||||
_value = _attribute->create(value);
|
||||
}
|
||||
}
|
||||
|
||||
AttributeValue::AttributeValue(const AttributeValue& other) :
|
||||
_attribute(other._attribute) {
|
||||
|
||||
if (_attribute) {
|
||||
_value = _attribute->create(&other._value);
|
||||
}
|
||||
}
|
||||
|
||||
AttributeValue::~AttributeValue() {
|
||||
if (_attribute) {
|
||||
_attribute->destroy(_value);
|
||||
}
|
||||
}
|
||||
|
||||
AttributeValue& AttributeValue::operator=(const AttributeValue& other) {
|
||||
if (_attribute) {
|
||||
_attribute->destroy(_value);
|
||||
}
|
||||
if ((_attribute = other._attribute)) {
|
||||
_value = _attribute->create(&other._value);
|
||||
}
|
||||
}
|
||||
|
||||
void* AttributeValue::copy() const {
|
||||
return _attribute->create(&_value);
|
||||
}
|
||||
|
||||
bool AttributeValue::isDefault() const {
|
||||
return !_attribute || _attribute->equal(_value, _attribute->getDefaultValue());
|
||||
}
|
||||
|
||||
bool AttributeValue::operator==(const AttributeValue& other) const {
|
||||
return _attribute == other._attribute && (!_attribute || _attribute->equal(_value, other._value));
|
||||
}
|
||||
|
||||
bool AttributeValue::operator==(void* other) const {
|
||||
return _attribute && _attribute->equal(_value, other);
|
||||
}
|
||||
|
||||
Attribute::Attribute(const QString& name) : _name(name) {
|
||||
}
|
||||
|
||||
Attribute::~Attribute() {
|
||||
}
|
||||
|
||||
|
|
|
@ -10,12 +10,15 @@
|
|||
#define __interface__AttributeRegistry__
|
||||
|
||||
#include <QHash>
|
||||
#include <QSharedPointer>
|
||||
#include <QString>
|
||||
|
||||
typedef int AttributeID;
|
||||
#include "Bitstream.h"
|
||||
|
||||
class Attribute;
|
||||
|
||||
typedef QSharedPointer<Attribute> AttributePointer;
|
||||
|
||||
/// Maintains information about metavoxel attribute types.
|
||||
class AttributeRegistry {
|
||||
public:
|
||||
|
@ -25,36 +28,103 @@ public:
|
|||
|
||||
AttributeRegistry();
|
||||
|
||||
/// Returns a unique id for the described attribute, creating one if necessary.
|
||||
AttributeID getAttributeID(const QString& name);
|
||||
/// Registers an attribute with the system.
|
||||
/// \return either the pointer passed as an argument, if the attribute wasn't already registered, or the existing
|
||||
/// attribute
|
||||
AttributePointer registerAttribute(AttributePointer attribute);
|
||||
|
||||
/// Returns the identified attribute, or an invalid attribute if not found.
|
||||
Attribute getAttribute(AttributeID id) const;
|
||||
/// Retrieves an attribute by name.
|
||||
AttributePointer getAttribute(const QString& name) const { return _attributes.value(name); }
|
||||
|
||||
private:
|
||||
|
||||
static AttributeRegistry _instance;
|
||||
|
||||
AttributeID _lastAttributeID;
|
||||
QHash<QString, AttributeID> _attributeIDs;
|
||||
QHash<AttributeID, Attribute> _attributes;
|
||||
QHash<QString, AttributePointer> _attributes;
|
||||
};
|
||||
|
||||
/// Pairs an attribute value with its type.
|
||||
class AttributeValue {
|
||||
public:
|
||||
|
||||
AttributeValue(const AttributePointer& attribute = AttributePointer(), void* const* value = NULL);
|
||||
AttributeValue(const AttributeValue& other);
|
||||
~AttributeValue();
|
||||
|
||||
AttributeValue& operator=(const AttributeValue& other);
|
||||
|
||||
AttributePointer getAttribute() const { return _attribute; }
|
||||
void* getValue() const { return _value; }
|
||||
|
||||
void* copy() const;
|
||||
|
||||
bool isDefault() const;
|
||||
|
||||
bool operator==(const AttributeValue& other) const;
|
||||
bool operator==(void* other) const;
|
||||
|
||||
private:
|
||||
|
||||
AttributePointer _attribute;
|
||||
void* _value;
|
||||
};
|
||||
|
||||
/// Represents a registered attribute.
|
||||
class Attribute {
|
||||
public:
|
||||
|
||||
Attribute(AttributeID id = 0, const QString& name = QString());
|
||||
Attribute(const QString& name);
|
||||
virtual ~Attribute();
|
||||
|
||||
bool isValid() const { return !_name.isNull(); }
|
||||
|
||||
AttributeID getID() const { return _id; }
|
||||
const QString& getName() const { return _name; }
|
||||
|
||||
virtual void* create(void* const* copy = NULL) const = 0;
|
||||
virtual void destroy(void* value) const = 0;
|
||||
|
||||
virtual bool read(Bitstream& in, void*& value) const = 0;
|
||||
virtual bool write(Bitstream& out, void* value) const = 0;
|
||||
|
||||
virtual bool equal(void* first, void* second) const = 0;
|
||||
|
||||
virtual void* createAveraged(void* values[]) const = 0;
|
||||
|
||||
virtual void* getDefaultValue() const = 0;
|
||||
|
||||
private:
|
||||
|
||||
AttributeID _id;
|
||||
QString _name;
|
||||
};
|
||||
|
||||
/// A simple attribute class that stores its values inline.
|
||||
template<class T, int bits> class InlineAttribute : public Attribute {
|
||||
public:
|
||||
|
||||
InlineAttribute(const QString& name, T defaultValue = T()) : Attribute(name), _defaultValue(*(void**)&defaultValue) { }
|
||||
|
||||
virtual void* create(void* const* copy = NULL) const { return (copy == NULL) ? _defaultValue : *copy; }
|
||||
virtual void destroy(void* value) const { /* no-op */ }
|
||||
|
||||
virtual bool read(Bitstream& in, void*& value) const { value = getDefaultValue(); in.read(&value, bits); return false; }
|
||||
virtual bool write(Bitstream& out, void* value) const { out.write(&value, bits); return false; }
|
||||
|
||||
virtual bool equal(void* first, void* second) const { return first == second; }
|
||||
|
||||
virtual void* createAveraged(void* values[]) const;
|
||||
|
||||
virtual void* getDefaultValue() const { return _defaultValue; }
|
||||
|
||||
private:
|
||||
|
||||
void* _defaultValue;
|
||||
};
|
||||
|
||||
template<class T, int bits> inline void* InlineAttribute<T, bits>::createAveraged(void* values[]) const {
|
||||
T total = T();
|
||||
for (int i = 0; i < 8; i++) {
|
||||
total += *(T*)(values + i);
|
||||
}
|
||||
total /= 8;
|
||||
return *(void**)&total;
|
||||
}
|
||||
|
||||
#endif /* defined(__interface__AttributeRegistry__) */
|
||||
|
|
|
@ -8,7 +8,119 @@
|
|||
|
||||
#include "MetavoxelData.h"
|
||||
|
||||
void MetavoxelData::visitVoxels(const QVector<AttributeID>& attributes, VoxelVisitor* visitor) {
|
||||
MetavoxelData::~MetavoxelData() {
|
||||
for (QHash<AttributePointer, MetavoxelNode*>::const_iterator it = _roots.constBegin(); it != _roots.constEnd(); it++) {
|
||||
it.value()->destroy(it.key());
|
||||
delete it.value();
|
||||
}
|
||||
}
|
||||
|
||||
void MetavoxelData::visitVoxels(const QVector<Attribute*>& attributes, VoxelVisitor* visitor) {
|
||||
// map attributes to layers, indices
|
||||
|
||||
}
|
||||
|
||||
void MetavoxelData::setAttributeValue(const MetavoxelPath& path, const AttributeValue& attributeValue) {
|
||||
MetavoxelNode*& node = _roots[attributeValue.getAttribute()];
|
||||
if (node == NULL) {
|
||||
node = new MetavoxelNode(attributeValue.getAttribute());
|
||||
}
|
||||
if (node->setAttributeValue(path, 0, attributeValue)) {
|
||||
node->destroy(attributeValue.getAttribute());
|
||||
delete node;
|
||||
_roots.remove(attributeValue.getAttribute());
|
||||
}
|
||||
}
|
||||
|
||||
AttributeValue MetavoxelData::getAttributeValue(const MetavoxelPath& path, const AttributePointer& attribute) const {
|
||||
MetavoxelNode* node = _roots.value(attribute);
|
||||
if (node == NULL) {
|
||||
return AttributeValue(attribute);
|
||||
}
|
||||
for (int i = 0, n = path.getSize(); i < n; i++) {
|
||||
int index = path[i];
|
||||
MetavoxelNode* child = node->getChild(i);
|
||||
if (child == NULL) {
|
||||
return AttributeValue(attribute);
|
||||
}
|
||||
node = child;
|
||||
}
|
||||
return node->getAttributeValue(attribute);
|
||||
}
|
||||
|
||||
MetavoxelNode::MetavoxelNode(const AttributeValue& attributeValue) {
|
||||
_attributeValue = attributeValue.copy();
|
||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||
_children[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool MetavoxelNode::setAttributeValue(const MetavoxelPath& path, int index, const AttributeValue& attributeValue) {
|
||||
if (index == path.getSize()) {
|
||||
setAttributeValue(attributeValue);
|
||||
return attributeValue.isDefault();
|
||||
}
|
||||
int element = path[index];
|
||||
if (_children[element] == NULL) {
|
||||
_children[element] = new MetavoxelNode(attributeValue.getAttribute());
|
||||
}
|
||||
if (_children[element]->setAttributeValue(path, index + 1, attributeValue)) {
|
||||
_children[element]->destroy(attributeValue.getAttribute());
|
||||
delete _children[element];
|
||||
_children[element] = NULL;
|
||||
if (allChildrenNull()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
void* childValues[CHILD_COUNT];
|
||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||
childValues[i] = (_children[i] == NULL) ? attributeValue.getAttribute()->getDefaultValue() :
|
||||
_children[i]->_attributeValue;
|
||||
}
|
||||
attributeValue.getAttribute()->destroy(_attributeValue);
|
||||
_attributeValue = attributeValue.getAttribute()->createAveraged(childValues);
|
||||
return false;
|
||||
}
|
||||
|
||||
void MetavoxelNode::setAttributeValue(const AttributeValue& attributeValue) {
|
||||
attributeValue.getAttribute()->destroy(_attributeValue);
|
||||
_attributeValue = attributeValue.copy();
|
||||
}
|
||||
|
||||
AttributeValue MetavoxelNode::getAttributeValue(const AttributePointer& attribute) const {
|
||||
return AttributeValue(attribute, &_attributeValue);
|
||||
}
|
||||
|
||||
void MetavoxelNode::destroy(const AttributePointer& attribute) {
|
||||
attribute->destroy(_attributeValue);
|
||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||
if (_children[i]) {
|
||||
_children[i]->destroy(attribute);
|
||||
delete _children[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MetavoxelNode::allChildrenNull() const {
|
||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||
if (_children[i] != NULL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int MetavoxelPath::operator[](int index) const {
|
||||
return _array.at(index * BITS_PER_ELEMENT) | (_array.at(index * BITS_PER_ELEMENT + 1) << 1) |
|
||||
(_array.at(index * BITS_PER_ELEMENT + 2) << 2);
|
||||
}
|
||||
|
||||
MetavoxelPath& MetavoxelPath::operator+=(int element) {
|
||||
int offset = _array.size();
|
||||
_array.resize(offset + BITS_PER_ELEMENT);
|
||||
_array.setBit(offset, element & 0x01);
|
||||
_array.setBit(offset + 1, (element >> 1) & 0x01);
|
||||
_array.setBit(offset + 2, element >> 2);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,36 +9,35 @@
|
|||
#ifndef __interface__MetavoxelData__
|
||||
#define __interface__MetavoxelData__
|
||||
|
||||
#include <QBitArray>
|
||||
#include <QHash>
|
||||
#include <QScopedPointer>
|
||||
#include <QVector>
|
||||
|
||||
#include "AttributeRegistry.h"
|
||||
|
||||
class MetavoxelLayer;
|
||||
class MetavoxelNode;
|
||||
class MetavoxelPath;
|
||||
class VoxelVisitor;
|
||||
|
||||
/// The base metavoxel representation shared between server and client.
|
||||
class MetavoxelData {
|
||||
public:
|
||||
|
||||
~MetavoxelData();
|
||||
|
||||
/// Applies the specified function to the contained voxels.
|
||||
/// \param attributes the list of attributes desired
|
||||
void visitVoxels(const QVector<AttributeID>& attributes, VoxelVisitor* visitor);
|
||||
void visitVoxels(const QVector<Attribute*>& attributes, VoxelVisitor* visitor);
|
||||
|
||||
/// Sets the attribute value corresponding to the specified path.
|
||||
void setAttributeValue(const MetavoxelPath& path, const AttributeValue& attributeValue);
|
||||
|
||||
/// Retrieves the attribute value corresponding to the specified path.
|
||||
AttributeValue getAttributeValue(const MetavoxelPath& path, const AttributePointer& attribute) const;
|
||||
|
||||
private:
|
||||
|
||||
QVector<MetavoxelLayer> _layers;
|
||||
};
|
||||
|
||||
/// A single layer of metavoxel data (a tree containing nodes of the same type).
|
||||
class MetavoxelLayer {
|
||||
public:
|
||||
|
||||
private:
|
||||
|
||||
QVector<AttributeID> _attributes;
|
||||
QScopedPointer<MetavoxelNode> _root;
|
||||
QHash<AttributePointer, MetavoxelNode*> _roots;
|
||||
};
|
||||
|
||||
/// A single node within a metavoxel layer.
|
||||
|
@ -47,12 +46,48 @@ public:
|
|||
|
||||
static const int CHILD_COUNT = 8;
|
||||
|
||||
|
||||
MetavoxelNode(const AttributeValue& attributeValue);
|
||||
|
||||
/// Descends the voxel tree in order to set the value of a node.
|
||||
/// \param path the path to follow
|
||||
/// \param index the position in the path
|
||||
/// \return whether or not the node is entirely equal to the default attribute, and can thus be collapsed
|
||||
bool setAttributeValue(const MetavoxelPath& path, int index, const AttributeValue& attributeValue);
|
||||
|
||||
void setAttributeValue(const AttributeValue& attributeValue);
|
||||
|
||||
AttributeValue getAttributeValue(const AttributePointer& attribute) const;
|
||||
|
||||
MetavoxelNode* getChild(int index) const { return _children[index]; }
|
||||
void setChild(int index, MetavoxelNode* child) { _children[index] = child; }
|
||||
|
||||
void destroy(const AttributePointer& attribute);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(MetavoxelNode)
|
||||
|
||||
void* _attributeValues;
|
||||
QScopedPointer<MetavoxelNode> _children[CHILD_COUNT];
|
||||
bool allChildrenNull() const;
|
||||
|
||||
void* _attributeValue;
|
||||
MetavoxelNode* _children[CHILD_COUNT];
|
||||
};
|
||||
|
||||
/// A path down an octree.
|
||||
class MetavoxelPath {
|
||||
public:
|
||||
|
||||
int getSize() const { return _array.size() / BITS_PER_ELEMENT; }
|
||||
bool isEmpty() const { return _array.isEmpty(); }
|
||||
|
||||
int operator[](int index) const;
|
||||
|
||||
MetavoxelPath& operator+=(int element);
|
||||
|
||||
private:
|
||||
|
||||
static const int BITS_PER_ELEMENT = 3;
|
||||
|
||||
QBitArray _array;
|
||||
};
|
||||
|
||||
/// Interface for visitors to voxels.
|
||||
|
|
Loading…
Reference in a new issue