More work on metavoxel bits.

This commit is contained in:
Andrzej Kapolka 2013-12-06 17:12:29 -08:00
parent dfbf896304
commit 29870877a8
9 changed files with 209 additions and 95 deletions

View file

@ -20,7 +20,7 @@ const float CAMERA_FIRST_PERSON_MODE_TIGHTNESS = 100.0f;
const float CAMERA_THIRD_PERSON_MODE_UP_SHIFT = -0.2f;
const float CAMERA_THIRD_PERSON_MODE_DISTANCE = 1.5f;
const float CAMERA_THIRD_PERSON_MODE_TIGHTNESS = 8.0f;
const float CAMERA_THIRD_PERSON_MODE_TIGHTNESS = 0.0f;
const float CAMERA_MIRROR_MODE_UP_SHIFT = 0.0f;
const float CAMERA_MIRROR_MODE_DISTANCE = 0.17f;

View file

@ -0,0 +1,31 @@
//
// AttributeRegistry.cpp
// metavoxels
//
// Created by Andrzej Kapolka on 12/6/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#include "AttributeRegistry.h"
AttributeRegistry AttributeRegistry::_instance;
AttributeRegistry::AttributeRegistry() : _lastAttributeID(0) {
}
AttributeID AttributeRegistry::getAttributeID(const QString& name) {
AttributeID& id = _attributeIDs[name];
if (id == 0) {
id = ++_lastAttributeID;
_attributes.insert(id, Attribute(id, name));
}
return id;
}
Attribute AttributeRegistry::getAttribute(AttributeID id) const {
return _attributes.value(id);
}
Attribute::Attribute(AttributeID id, const QString& name) :
_id(id), _name(name) {
}

View file

@ -0,0 +1,60 @@
//
// AttributeRegistry.h
// metavoxels
//
// Created by Andrzej Kapolka on 12/6/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __interface__AttributeRegistry__
#define __interface__AttributeRegistry__
#include <QHash>
#include <QString>
typedef int AttributeID;
class Attribute;
/// Maintains information about metavoxel attribute types.
class AttributeRegistry {
public:
/// Returns a pointer to the singleton registry instance.
static AttributeRegistry* getInstance() { return &_instance; }
AttributeRegistry();
/// Returns a unique id for the described attribute, creating one if necessary.
AttributeID getAttributeID(const QString& name);
/// Returns the identified attribute, or an invalid attribute if not found.
Attribute getAttribute(AttributeID id) const;
private:
static AttributeRegistry _instance;
AttributeID _lastAttributeID;
QHash<QString, AttributeID> _attributeIDs;
QHash<AttributeID, Attribute> _attributes;
};
/// Represents a registered attribute.
class Attribute {
public:
Attribute(AttributeID id = 0, const QString& name = QString());
bool isValid() const { return !_name.isNull(); }
AttributeID getID() const { return _id; }
const QString& getName() const { return _name; }
private:
AttributeID _id;
QString _name;
};
#endif /* defined(__interface__AttributeRegistry__) */

View file

@ -14,11 +14,41 @@ Bitstream::Bitstream(QDataStream& underlying)
: _underlying(underlying), _byte(0), _position(0) {
}
Bitstream& Bitstream::write(const void* data, int bits) {
const int BITS_IN_BYTE = 8;
const int LAST_BIT_POSITION = BITS_IN_BYTE - 1;
Bitstream& Bitstream::write(const void* data, int bits, int offset) {
const quint8* source = (const quint8*)data;
while (bits > 0) {
int bitsToWrite = qMin(BITS_IN_BYTE - _position, qMin(BITS_IN_BYTE - offset, bits));
_byte |= ((*source >> offset) & ((1 << bitsToWrite) - 1)) << _position;
if ((_position += bitsToWrite) == BITS_IN_BYTE) {
flush();
}
if ((offset += bitsToWrite) == BITS_IN_BYTE) {
source++;
offset = 0;
}
bits -= bitsToWrite;
}
return *this;
}
Bitstream& Bitstream::read(void* data, int bits) {
Bitstream& Bitstream::read(void* data, int bits, int offset) {
quint8* dest = (quint8*)data;
while (bits > 0) {
if (_position == 0) {
_underlying >> _byte;
}
int bitsToRead = qMin(BITS_IN_BYTE - _position, qMin(BITS_IN_BYTE - offset, bits));
*dest |= ((_byte >> _position) & ((1 << bitsToRead) - 1)) << offset;
_position = (_position + bitsToRead) & LAST_BIT_POSITION;
if ((offset += bitsToRead) == BITS_IN_BYTE) {
dest++;
offset = 0;
}
bits -= bitsToRead;
}
return *this;
}
@ -30,13 +60,12 @@ void Bitstream::flush() {
}
}
const int LAST_BIT_POSITION = 7;
Bitstream& Bitstream::operator<<(bool value) {
if (value) {
_byte |= (1 << _position);
}
if (_position++ == LAST_BIT_POSITION) {
if (++_position == BITS_IN_BYTE) {
flush();
}
return *this;

View file

@ -19,8 +19,15 @@ public:
Bitstream(QDataStream& underlying);
Bitstream& write(const void* data, int bits);
Bitstream& read(void* data, int bits);
/// Writes a set of bits to the underlying stream.
/// \param bits the number of bits to write
/// \param offset the offset of the first bit
Bitstream& write(const void* data, int bits, int offset = 0);
/// Reads a set of bits from the underlying stream.
/// \param bits the number of bits to read
/// \param offset the offset of the first bit
Bitstream& read(void* data, int bits, int offset = 0);
/// Flushes any unwritten bits to the underlying stream.
void flush();

View file

@ -1,50 +0,0 @@
//
// Metavoxels.cpp
// metavoxels
//
// Created by Andrzej Kapolka on 12/2/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#include "Bitstream.h"
#include "Metavoxel.h"
bool Metavoxel::isLeaf() const {
for (int i = 0; i < CHILD_COUNT; i++) {
if (_children[i]) {
return false;
}
}
return true;
}
Bitstream& operator<<(Bitstream& stream, const Metavoxel& voxel) {
for (int i = 0; i < Metavoxel::CHILD_COUNT; i++) {
const Metavoxel* child = voxel.getChild(i);
if (child) {
stream << true << *child;
} else {
stream << false;
}
}
return stream;
}
Bitstream& operator>>(Bitstream& stream, Metavoxel& voxel) {
for (int i = 0; i < Metavoxel::CHILD_COUNT; i++) {
bool childExists;
stream >> childExists;
Metavoxel* child = voxel.getChild(i);
if (childExists) {
if (!child) {
voxel.setChild(i, new Metavoxel);
}
stream >> *child;
} else if (child) {
voxel.setChild(i, NULL);
}
}
return stream;
}

View file

@ -1,38 +0,0 @@
//
// Metavoxel.h
// metavoxels
//
// Created by Andrzej Kapolka on 12/2/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __interface__Metavoxel__
#define __interface__Metavoxel__
#include <QScopedPointer>
class Bitstream;
/// A single node in a metavoxel tree.
class Metavoxel {
public:
static const int CHILD_COUNT = 8;
/// Sets the child at the specified index. Note that this object will assume ownership if non-null.
void setChild(int index, Metavoxel* child) { _children[index].reset(child); }
const Metavoxel* getChild(int index) const { return _children[index].data(); }
Metavoxel* getChild(int index) { return _children[index].data(); }
bool isLeaf() const;
private:
QScopedPointer<Metavoxel> _children[CHILD_COUNT];
};
Bitstream& operator<<(Bitstream& stream, const Metavoxel& voxel);
Bitstream& operator>>(Bitstream& stream, Metavoxel& voxel);
#endif /* defined(__interface__Metavoxel__) */

View file

@ -0,0 +1,11 @@
//
// MetavoxelData.cpp
// metavoxels
//
// Created by Andrzej Kapolka on 12/6/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#include "MetavoxelData.h"

View file

@ -0,0 +1,64 @@
//
// MetavoxelData.h
// metavoxels
//
// Created by Andrzej Kapolka on 12/6/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __interface__MetavoxelData__
#define __interface__MetavoxelData__
#include <QScopedPointer>
#include <QVector>
#include "AttributeRegistry.h"
class MetavoxelNode;
class VoxelVisitor;
/// The base metavoxel representation shared between server and client.
class MetavoxelData {
public:
/// Applies the specified function to the contained voxels.
/// \param attributes the list of attributes desired
void visitVoxels(const QVector<AttributeID>& attributes, VoxelVisitor* visitor);
private:
};
/// A single layer of metavoxel data (a tree containing nodes of the same type).
class MetavoxelLayer {
public:
private:
QScopedPointer<MetavoxelNode> _root;
};
/// A single node within a metavoxel layer.
class MetavoxelNode {
public:
static const int CHILD_COUNT = 8;
private:
QScopedPointer<MetavoxelNode> _children[CHILD_COUNT];
};
/// Interface for visitors to voxels.
class VoxelVisitor {
public:
/// Visits a voxel.
/// \param attributeValues the values of the desired attributes
virtual void visit(const QVector<void*>& attributeValues) = 0;
};
#endif /* defined(__interface__MetavoxelData__) */