mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-05 02:00:06 +02:00
Basic voxelization.
This commit is contained in:
parent
061d7719d4
commit
d706e23012
5 changed files with 138 additions and 23 deletions
|
@ -656,35 +656,45 @@ bool SetSpannerTool::appliesTo(const AttributePointer& attribute) const {
|
|||
return attribute == AttributeRegistry::getInstance()->getSpannersAttribute();
|
||||
}
|
||||
|
||||
glm::vec3 DIRECTION_VECTORS[] = { glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f),
|
||||
glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, 0.0f, 1.0f) };
|
||||
glm::quat DIRECTION_ROTATIONS[] = {
|
||||
rotationBetween(glm::vec3(-1.0f, 0.0f, 0.0f), IDENTITY_FRONT),
|
||||
rotationBetween(glm::vec3(1.0f, 0.0f, 0.0f), IDENTITY_FRONT),
|
||||
rotationBetween(glm::vec3(0.0f, -1.0f, 0.0f), IDENTITY_FRONT),
|
||||
rotationBetween(glm::vec3(0.0f, 1.0f, 0.0f), IDENTITY_FRONT),
|
||||
rotationBetween(glm::vec3(0.0f, 0.0f, -1.0f), IDENTITY_FRONT),
|
||||
rotationBetween(glm::vec3(0.0f, 0.0f, 1.0f), IDENTITY_FRONT) };
|
||||
|
||||
/// Represents a view from one direction of the spanner to be voxelized.
|
||||
class DirectionImages {
|
||||
public:
|
||||
QImage color;
|
||||
QVector<float> depth;
|
||||
glm::vec3 minima;
|
||||
glm::vec3 maxima;
|
||||
glm::vec3 scale;
|
||||
};
|
||||
|
||||
class Voxelizer : public QRunnable {
|
||||
public:
|
||||
|
||||
Voxelizer(float size, const Box& bounds, const QVector<DirectionImages>& directionImages);
|
||||
Voxelizer(float size, const Box& bounds, float granularity, const QVector<DirectionImages>& directionImages);
|
||||
|
||||
virtual void run();
|
||||
|
||||
private:
|
||||
|
||||
void voxelize(const glm::vec3& minimum);
|
||||
void voxelize(const glm::vec3& center);
|
||||
|
||||
float _size;
|
||||
Box _bounds;
|
||||
float _granularity;
|
||||
QVector<DirectionImages> _directionImages;
|
||||
};
|
||||
|
||||
Voxelizer::Voxelizer(float size, const Box& bounds, const QVector<DirectionImages>& directionImages) :
|
||||
Voxelizer::Voxelizer(float size, const Box& bounds, float granularity, const QVector<DirectionImages>& directionImages) :
|
||||
_size(size),
|
||||
_bounds(bounds),
|
||||
_granularity(granularity),
|
||||
_directionImages(directionImages) {
|
||||
}
|
||||
|
||||
|
@ -694,13 +704,108 @@ void Voxelizer::run() {
|
|||
for (float x = _bounds.minimum.x + halfSize; x < _bounds.maximum.x; x += _size) {
|
||||
for (float y = _bounds.minimum.y + halfSize; y < _bounds.maximum.y; y += _size) {
|
||||
for (float z = _bounds.minimum.z + halfSize; z < _bounds.maximum.z; z += _size) {
|
||||
|
||||
voxelize(glm::vec3(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Voxelizer::voxelize(const glm::vec3& minimum) {
|
||||
class VoxelizationVisitor : public MetavoxelVisitor {
|
||||
public:
|
||||
|
||||
VoxelizationVisitor(const QVector<DirectionImages>& directionImages, const glm::vec3& center, float granularity);
|
||||
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
|
||||
private:
|
||||
|
||||
QVector<DirectionImages> _directionImages;
|
||||
glm::vec3 _center;
|
||||
float _granularity;
|
||||
};
|
||||
|
||||
VoxelizationVisitor::VoxelizationVisitor(const QVector<DirectionImages>& directionImages,
|
||||
const glm::vec3& center, float granularity) :
|
||||
MetavoxelVisitor(QVector<AttributePointer>(), QVector<AttributePointer>() <<
|
||||
AttributeRegistry::getInstance()->getColorAttribute()),
|
||||
_directionImages(directionImages),
|
||||
_center(center),
|
||||
_granularity(granularity) {
|
||||
}
|
||||
|
||||
bool checkDisjoint(const DirectionImages& images, const glm::vec3& minimum, const glm::vec3& maximum) {
|
||||
for (int x = qMax(0, (int)minimum.x), xmax = qMin(images.color.width(), (int)maximum.x); x < xmax; x++) {
|
||||
for (int y = qMax(0, (int)minimum.y), ymax = qMin(images.color.height(), (int)maximum.y); y < ymax; y++) {
|
||||
float depth = 1.0f - images.depth.at(y * images.color.width() + x);
|
||||
if (depth - minimum.z >= 0.0f) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int VoxelizationVisitor::visit(MetavoxelInfo& info) {
|
||||
float halfSize = info.size * 0.5f;
|
||||
glm::vec3 center = info.minimum + _center + glm::vec3(halfSize, halfSize, halfSize);
|
||||
if (info.size > _granularity) {
|
||||
for (unsigned int i = 0; i < sizeof(DIRECTION_ROTATIONS) / sizeof(DIRECTION_ROTATIONS[0]); i++) {
|
||||
glm::vec3 rotated = DIRECTION_ROTATIONS[i] * center;
|
||||
const DirectionImages& images = _directionImages.at(i);
|
||||
glm::vec3 relative = (rotated - images.minima) * images.scale;
|
||||
glm::vec3 extents = images.scale * halfSize;
|
||||
glm::vec3 minimum = relative - extents;
|
||||
glm::vec3 maximum = relative + extents;
|
||||
if (checkDisjoint(images, minimum, maximum)) {
|
||||
info.outputValues[0] = AttributeValue(_outputs.at(0));
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
}
|
||||
return DEFAULT_ORDER;
|
||||
}
|
||||
QRgb closestColor;
|
||||
float closestDistance = FLT_MAX;
|
||||
for (unsigned int i = 0; i < sizeof(DIRECTION_ROTATIONS) / sizeof(DIRECTION_ROTATIONS[0]); i++) {
|
||||
glm::vec3 rotated = DIRECTION_ROTATIONS[i] * center;
|
||||
const DirectionImages& images = _directionImages.at(i);
|
||||
glm::vec3 relative = (rotated - images.minima) * images.scale;
|
||||
int x = qMax(qMin((int)glm::round(relative.x), images.color.width() - 1), 0);
|
||||
int y = qMax(qMin((int)glm::round(relative.y), images.color.height() - 1), 0);
|
||||
float depth = 1.0f - images.depth.at(y * images.color.width() + x);
|
||||
float distance = depth - relative.z;
|
||||
if (distance < 0.0f) {
|
||||
info.outputValues[0] = AttributeValue(_outputs.at(0));
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
QRgb color = images.color.pixel(x, y);
|
||||
if (distance < EPSILON) {
|
||||
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline<QRgb>(color));
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
if (distance < closestDistance) {
|
||||
closestColor = color;
|
||||
closestDistance = distance;
|
||||
}
|
||||
}
|
||||
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline<QRgb>(closestColor));
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
|
||||
void Voxelizer::voxelize(const glm::vec3& center) {
|
||||
MetavoxelData data;
|
||||
data.setSize(_size);
|
||||
|
||||
qDebug() << "Started voxelizing " << center.x << center.y << center.z;
|
||||
|
||||
VoxelizationVisitor visitor(_directionImages, center, _granularity);
|
||||
data.guide(visitor);
|
||||
|
||||
qDebug() << "Finished voxelizing " << center.x << center.y << center.z;
|
||||
|
||||
MetavoxelEditMessage edit = { QVariant::fromValue(SetDataEdit(
|
||||
center - glm::vec3(_size, _size, _size) * 0.5f, data, false)) };
|
||||
QMetaObject::invokeMethod(Application::getInstance()->getMetavoxels(), "applyEdit",
|
||||
Q_ARG(const MetavoxelEditMessage&, edit), Q_ARG(bool, true));
|
||||
}
|
||||
|
||||
void SetSpannerTool::applyEdit(const AttributePointer& attribute, const SharedObjectPointer& spanner) {
|
||||
|
@ -725,12 +830,11 @@ void SetSpannerTool::applyEdit(const AttributePointer& attribute, const SharedOb
|
|||
|
||||
QVector<DirectionImages> directionImages;
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(DIRECTION_VECTORS) / sizeof(DIRECTION_VECTORS[0]); i++) {
|
||||
glm::quat rotation = rotationBetween(DIRECTION_VECTORS[i], IDENTITY_FRONT);
|
||||
for (unsigned int i = 0; i < sizeof(DIRECTION_ROTATIONS) / sizeof(DIRECTION_ROTATIONS[0]); i++) {
|
||||
glm::vec3 minima(FLT_MAX, FLT_MAX, FLT_MAX);
|
||||
glm::vec3 maxima(-FLT_MAX, -FLT_MAX, -FLT_MAX);
|
||||
for (int j = 0; j < Box::VERTEX_COUNT; j++) {
|
||||
glm::vec3 rotated = rotation * cellBounds.getVertex(j);
|
||||
glm::vec3 rotated = DIRECTION_ROTATIONS[i] * cellBounds.getVertex(j);
|
||||
minima = glm::min(minima, rotated);
|
||||
maxima = glm::max(maxima, rotated);
|
||||
}
|
||||
|
@ -742,16 +846,20 @@ void SetSpannerTool::applyEdit(const AttributePointer& attribute, const SharedOb
|
|||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glLoadIdentity();
|
||||
glOrtho(minima.x, maxima.x, minima.y, maxima.y, -minima.z, -maxima.z);
|
||||
glOrtho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glm::vec3 axis = glm::axis(rotation);
|
||||
glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
|
||||
glm::vec3 axis = glm::axis(DIRECTION_ROTATIONS[i]);
|
||||
glRotatef(glm::degrees(glm::angle(DIRECTION_ROTATIONS[i])), axis.x, axis.y, axis.z);
|
||||
|
||||
Application::getInstance()->setupWorldLight();
|
||||
|
||||
spannerData->getRenderer()->render(1.0f, glm::vec3(), 0.0f);
|
||||
|
||||
DirectionImages images = { QImage(width, height, QImage::Format_ARGB32), QVector<float>(width * height) };
|
||||
DirectionImages images = { QImage(width, height, QImage::Format_ARGB32),
|
||||
QVector<float>(width * height), minima, maxima, glm::vec3(width / (maxima.x - minima.x),
|
||||
height / (maxima.y - minima.y), 1.0f / (maxima.z - minima.z)) };
|
||||
glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, images.color.bits());
|
||||
glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, images.depth.data());
|
||||
directionImages.append(images);
|
||||
|
@ -771,5 +879,6 @@ void SetSpannerTool::applyEdit(const AttributePointer& attribute, const SharedOb
|
|||
glViewport(0, 0, Application::getInstance()->getGLWidget()->width(), Application::getInstance()->getGLWidget()->height());
|
||||
|
||||
// send the images off to the lab for processing
|
||||
QThreadPool::globalInstance()->start(new Voxelizer(size, cellBounds, directionImages));
|
||||
QThreadPool::globalInstance()->start(new Voxelizer(size, cellBounds,
|
||||
spannerData->getVoxelizationGranularity(), directionImages));
|
||||
}
|
||||
|
|
|
@ -373,7 +373,12 @@ static void setNode(const AttributeValue& value, MetavoxelNode*& node, const glm
|
|||
setNode(value, node, other, blend);
|
||||
return;
|
||||
}
|
||||
if (!node) {
|
||||
if (node) {
|
||||
MetavoxelNode* oldNode = node;
|
||||
node = new MetavoxelNode(value.getAttribute(), oldNode);
|
||||
oldNode->decrementReferenceCount(value.getAttribute());
|
||||
|
||||
} else {
|
||||
node = new MetavoxelNode(value);
|
||||
}
|
||||
int index = 0;
|
||||
|
@ -403,7 +408,7 @@ static void setNode(const AttributeValue& value, MetavoxelNode*& node, const glm
|
|||
|
||||
void MetavoxelData::set(const glm::vec3& minimum, const MetavoxelData& data, bool blend) {
|
||||
// expand to fit the entire data
|
||||
Box bounds = minimum + glm::vec3(data.getSize(), data.getSize(), data.getSize());
|
||||
Box bounds(minimum, minimum + glm::vec3(data.getSize(), data.getSize(), data.getSize()));
|
||||
while (!getBounds().contains(bounds)) {
|
||||
expand();
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ public:
|
|||
|
||||
MetavoxelData& operator=(const MetavoxelData& other);
|
||||
|
||||
void setSize(float size) { _size = size; }
|
||||
float getSize() const { return _size; }
|
||||
|
||||
glm::vec3 getMinimum() const { return glm::vec3(_size, _size, _size) * -0.5f; }
|
||||
|
|
|
@ -20,18 +20,17 @@ REGISTER_META_OBJECT(SharedObject)
|
|||
|
||||
SharedObject::SharedObject() :
|
||||
_id(++_lastID),
|
||||
_remoteID(0),
|
||||
_referenceCount(0) {
|
||||
_remoteID(0) {
|
||||
|
||||
_weakHash.insert(_id, this);
|
||||
}
|
||||
|
||||
void SharedObject::incrementReferenceCount() {
|
||||
_referenceCount++;
|
||||
_referenceCount.ref();
|
||||
}
|
||||
|
||||
void SharedObject::decrementReferenceCount() {
|
||||
if (--_referenceCount == 0) {
|
||||
if (!_referenceCount.deref()) {
|
||||
_weakHash.remove(_id);
|
||||
delete this;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#ifndef __interface__SharedObject__
|
||||
#define __interface__SharedObject__
|
||||
|
||||
#include <QAtomicInt>
|
||||
#include <QHash>
|
||||
#include <QMetaType>
|
||||
#include <QObject>
|
||||
|
@ -42,7 +43,7 @@ public:
|
|||
|
||||
void setRemoteID(int remoteID) { _remoteID = remoteID; }
|
||||
|
||||
int getReferenceCount() const { return _referenceCount; }
|
||||
int getReferenceCount() const { return _referenceCount.load(); }
|
||||
void incrementReferenceCount();
|
||||
void decrementReferenceCount();
|
||||
|
||||
|
@ -62,7 +63,7 @@ private:
|
|||
|
||||
int _id;
|
||||
int _remoteID;
|
||||
int _referenceCount;
|
||||
QAtomicInt _referenceCount;
|
||||
|
||||
static int _lastID;
|
||||
static WeakSharedObjectHash _weakHash;
|
||||
|
|
Loading…
Reference in a new issue