mirror of
https://github.com/lubosz/overte.git
synced 2025-04-14 14:46:55 +02:00
Cleanup on aisle three! Removed the color/normal/voxelized spanner bits, as
well as the throbbing/scripted guides and the notion of spanner masking.
This commit is contained in:
parent
ae71bb671b
commit
e08a0144c2
14 changed files with 75 additions and 1547 deletions
|
@ -1,31 +0,0 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// metavoxel_point.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 12/12/13.
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
uniform float pointScale;
|
||||
|
||||
// the interpolated normal
|
||||
varying vec4 normal;
|
||||
|
||||
void main(void) {
|
||||
// transform and store the normal for interpolation
|
||||
normal = vec4(normalize(gl_NormalMatrix * gl_Normal), 0.0);
|
||||
|
||||
// extract the first three components of the vertex for position
|
||||
gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xyz, 1.0);
|
||||
|
||||
// the final component is the size in world space
|
||||
gl_PointSize = pointScale * gl_Vertex.w / gl_Position.w;
|
||||
|
||||
// copy the color for interpolation
|
||||
gl_FrontColor = vec4(gl_Color.rgb, 0.0);
|
||||
}
|
|
@ -37,8 +37,6 @@ REGISTER_META_OBJECT(SphereRenderer)
|
|||
REGISTER_META_OBJECT(CuboidRenderer)
|
||||
REGISTER_META_OBJECT(StaticModelRenderer)
|
||||
|
||||
static int bufferPointVectorMetaTypeId = qRegisterMetaType<BufferPointVector>();
|
||||
|
||||
MetavoxelSystem::NetworkSimulation::NetworkSimulation(float dropRate, float repeatRate,
|
||||
int minimumDelay, int maximumDelay, int bandwidthLimit) :
|
||||
dropRate(dropRate),
|
||||
|
@ -59,8 +57,6 @@ void MetavoxelSystem::init() {
|
|||
MetavoxelClientManager::init();
|
||||
DefaultMetavoxelRendererImplementation::init();
|
||||
|
||||
_pointBufferAttribute = AttributeRegistry::getInstance()->registerAttribute(new BufferDataAttribute("pointBuffer"));
|
||||
|
||||
_heightfieldBufferAttribute = AttributeRegistry::getInstance()->registerAttribute(
|
||||
new BufferDataAttribute("heightfieldBuffer"));
|
||||
_heightfieldBufferAttribute->setLODThresholdMultiplier(
|
||||
|
@ -920,36 +916,6 @@ void MetavoxelSystemClient::sendDatagram(const QByteArray& data) {
|
|||
BufferData::~BufferData() {
|
||||
}
|
||||
|
||||
PointBuffer::PointBuffer(const BufferPointVector& points) :
|
||||
_points(points) {
|
||||
}
|
||||
|
||||
void PointBuffer::render(bool cursor) {
|
||||
// initialize buffer, etc. on first render
|
||||
if (!_buffer.isCreated()) {
|
||||
_buffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
|
||||
_buffer.create();
|
||||
_buffer.bind();
|
||||
_pointCount = _points.size();
|
||||
_buffer.allocate(_points.constData(), _pointCount * sizeof(BufferPoint));
|
||||
_points.clear();
|
||||
_buffer.release();
|
||||
}
|
||||
if (_pointCount == 0) {
|
||||
return;
|
||||
}
|
||||
_buffer.bind();
|
||||
|
||||
BufferPoint* point = 0;
|
||||
glVertexPointer(4, GL_FLOAT, sizeof(BufferPoint), &point->vertex);
|
||||
glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(BufferPoint), &point->color);
|
||||
glNormalPointer(GL_BYTE, sizeof(BufferPoint), &point->normal);
|
||||
|
||||
glDrawArrays(GL_POINTS, 0, _pointCount);
|
||||
|
||||
_buffer.release();
|
||||
}
|
||||
|
||||
const int HeightfieldBuffer::HEIGHT_BORDER = 1;
|
||||
const int HeightfieldBuffer::SHARED_EDGE = 1;
|
||||
const int HeightfieldBuffer::HEIGHT_EXTENSION = 2 * HeightfieldBuffer::HEIGHT_BORDER + HeightfieldBuffer::SHARED_EDGE;
|
||||
|
@ -1576,17 +1542,7 @@ AttributeValue BufferDataAttribute::inherit(const AttributeValue& parentValue) c
|
|||
}
|
||||
|
||||
void DefaultMetavoxelRendererImplementation::init() {
|
||||
if (!_pointProgram.isLinked()) {
|
||||
_pointProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +
|
||||
"shaders/metavoxel_point.vert");
|
||||
_pointProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
|
||||
"shaders/metavoxel_voxel_base.frag");
|
||||
_pointProgram.link();
|
||||
|
||||
_pointProgram.bind();
|
||||
_pointScaleLocation = _pointProgram.uniformLocation("pointScale");
|
||||
_pointProgram.release();
|
||||
|
||||
if (!_baseHeightfieldProgram.isLinked()) {
|
||||
_baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +
|
||||
"shaders/metavoxel_heightfield_base.vert");
|
||||
_baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
|
||||
|
@ -1631,76 +1587,6 @@ void DefaultMetavoxelRendererImplementation::init() {
|
|||
DefaultMetavoxelRendererImplementation::DefaultMetavoxelRendererImplementation() {
|
||||
}
|
||||
|
||||
class PointAugmentVisitor : public MetavoxelVisitor {
|
||||
public:
|
||||
|
||||
PointAugmentVisitor(const MetavoxelLOD& lod);
|
||||
|
||||
virtual void prepare(MetavoxelData* data);
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
virtual bool postVisit(MetavoxelInfo& info);
|
||||
|
||||
private:
|
||||
|
||||
BufferPointVector _points;
|
||||
float _pointLeafSize;
|
||||
};
|
||||
|
||||
PointAugmentVisitor::PointAugmentVisitor(const MetavoxelLOD& lod) :
|
||||
MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getColorAttribute() <<
|
||||
AttributeRegistry::getInstance()->getNormalAttribute(), QVector<AttributePointer>() <<
|
||||
Application::getInstance()->getMetavoxels()->getPointBufferAttribute(), lod) {
|
||||
}
|
||||
|
||||
const int ALPHA_RENDER_THRESHOLD = 0;
|
||||
|
||||
void PointAugmentVisitor::prepare(MetavoxelData* data) {
|
||||
MetavoxelVisitor::prepare(data);
|
||||
const float MAX_POINT_LEAF_SIZE = 64.0f;
|
||||
_pointLeafSize = qMin(data->getSize(), MAX_POINT_LEAF_SIZE);
|
||||
}
|
||||
|
||||
int PointAugmentVisitor::visit(MetavoxelInfo& info) {
|
||||
if (!info.isLeaf) {
|
||||
return (info.size > _pointLeafSize) ? DEFAULT_ORDER : (DEFAULT_ORDER | ALL_NODES_REST);
|
||||
}
|
||||
QRgb color = info.inputValues.at(0).getInlineValue<QRgb>();
|
||||
quint8 alpha = qAlpha(color);
|
||||
if (alpha > ALPHA_RENDER_THRESHOLD) {
|
||||
QRgb normal = info.inputValues.at(1).getInlineValue<QRgb>();
|
||||
BufferPoint point = { glm::vec4(info.minimum + glm::vec3(info.size, info.size, info.size) * 0.5f, info.size),
|
||||
{ quint8(qRed(color)), quint8(qGreen(color)), quint8(qBlue(color)) },
|
||||
{ quint8(qRed(normal)), quint8(qGreen(normal)), quint8(qBlue(normal)) } };
|
||||
_points.append(point);
|
||||
}
|
||||
if (info.size >= _pointLeafSize) {
|
||||
PointBuffer* buffer = NULL;
|
||||
if (!_points.isEmpty()) {
|
||||
BufferPointVector swapPoints;
|
||||
_points.swap(swapPoints);
|
||||
buffer = new PointBuffer(swapPoints);
|
||||
}
|
||||
BufferDataPointer pointer(buffer);
|
||||
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer));
|
||||
}
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
|
||||
bool PointAugmentVisitor::postVisit(MetavoxelInfo& info) {
|
||||
if (info.size != _pointLeafSize) {
|
||||
return false;
|
||||
}
|
||||
PointBuffer* buffer = NULL;
|
||||
if (!_points.isEmpty()) {
|
||||
BufferPointVector swapPoints;
|
||||
_points.swap(swapPoints);
|
||||
buffer = new PointBuffer(swapPoints);
|
||||
}
|
||||
BufferDataPointer pointer(buffer);
|
||||
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer));
|
||||
return true;
|
||||
}
|
||||
|
||||
class HeightfieldFetchVisitor : public MetavoxelVisitor {
|
||||
public:
|
||||
|
||||
|
@ -2749,15 +2635,9 @@ void DefaultMetavoxelRendererImplementation::augment(MetavoxelData& data, const
|
|||
while (expandedPrevious.getSize() < data.getSize()) {
|
||||
expandedPrevious.expand();
|
||||
}
|
||||
const AttributePointer& pointBufferAttribute = Application::getInstance()->getMetavoxels()->getPointBufferAttribute();
|
||||
MetavoxelNode* root = expandedPrevious.getRoot(pointBufferAttribute);
|
||||
if (root) {
|
||||
data.setRoot(pointBufferAttribute, root);
|
||||
root->incrementReferenceCount();
|
||||
}
|
||||
const AttributePointer& heightfieldBufferAttribute =
|
||||
Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute();
|
||||
root = expandedPrevious.getRoot(heightfieldBufferAttribute);
|
||||
MetavoxelNode* root = expandedPrevious.getRoot(heightfieldBufferAttribute);
|
||||
if (root) {
|
||||
data.setRoot(heightfieldBufferAttribute, root);
|
||||
root->incrementReferenceCount();
|
||||
|
@ -2769,10 +2649,6 @@ void DefaultMetavoxelRendererImplementation::augment(MetavoxelData& data, const
|
|||
data.setRoot(voxelBufferAttribute, root);
|
||||
root->incrementReferenceCount();
|
||||
}
|
||||
|
||||
PointAugmentVisitor pointAugmentVisitor(lod);
|
||||
data.guideToDifferent(expandedPrevious, pointAugmentVisitor);
|
||||
|
||||
HeightfieldRegionVisitor heightfieldRegionVisitor(lod);
|
||||
data.guideToDifferent(expandedPrevious, heightfieldRegionVisitor);
|
||||
|
||||
|
@ -2789,7 +2665,7 @@ public:
|
|||
|
||||
SpannerSimulateVisitor(float deltaTime, const MetavoxelLOD& lod);
|
||||
|
||||
virtual bool visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize);
|
||||
virtual bool visit(Spanner* spanner);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -2798,11 +2674,11 @@ private:
|
|||
|
||||
SpannerSimulateVisitor::SpannerSimulateVisitor(float deltaTime, const MetavoxelLOD& lod) :
|
||||
SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute(),
|
||||
QVector<AttributePointer>(), QVector<AttributePointer>(), QVector<AttributePointer>(), lod),
|
||||
QVector<AttributePointer>(), QVector<AttributePointer>(), lod),
|
||||
_deltaTime(deltaTime) {
|
||||
}
|
||||
|
||||
bool SpannerSimulateVisitor::visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize) {
|
||||
bool SpannerSimulateVisitor::visit(Spanner* spanner) {
|
||||
spanner->getRenderer()->simulate(_deltaTime);
|
||||
return true;
|
||||
}
|
||||
|
@ -2819,7 +2695,7 @@ public:
|
|||
SpannerRenderVisitor(const MetavoxelLOD& lod);
|
||||
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
virtual bool visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize);
|
||||
virtual bool visit(Spanner* spanner);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -2828,8 +2704,8 @@ private:
|
|||
|
||||
SpannerRenderVisitor::SpannerRenderVisitor(const MetavoxelLOD& lod) :
|
||||
SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute(),
|
||||
QVector<AttributePointer>(), QVector<AttributePointer>(), QVector<AttributePointer>(),
|
||||
lod, encodeOrder(Application::getInstance()->getDisplayViewFrustum()->getDirection())),
|
||||
QVector<AttributePointer>(), QVector<AttributePointer>(), lod,
|
||||
encodeOrder(Application::getInstance()->getDisplayViewFrustum()->getDirection())),
|
||||
_containmentDepth(INT_MAX) {
|
||||
}
|
||||
|
||||
|
@ -2845,9 +2721,9 @@ int SpannerRenderVisitor::visit(MetavoxelInfo& info) {
|
|||
return SpannerVisitor::visit(info);
|
||||
}
|
||||
|
||||
bool SpannerRenderVisitor::visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize) {
|
||||
bool SpannerRenderVisitor::visit(Spanner* spanner) {
|
||||
const glm::vec4 OPAQUE_WHITE(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
spanner->getRenderer()->render(OPAQUE_WHITE, SpannerRenderer::DEFAULT_MODE, clipMinimum, clipSize);
|
||||
spanner->getRenderer()->render(OPAQUE_WHITE, SpannerRenderer::DEFAULT_MODE);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2893,40 +2769,10 @@ void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, Metavox
|
|||
SpannerRenderVisitor spannerRenderVisitor(lod);
|
||||
data.guide(spannerRenderVisitor);
|
||||
|
||||
int viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
const int VIEWPORT_WIDTH_INDEX = 2;
|
||||
const int VIEWPORT_HEIGHT_INDEX = 3;
|
||||
float viewportWidth = viewport[VIEWPORT_WIDTH_INDEX];
|
||||
float viewportHeight = viewport[VIEWPORT_HEIGHT_INDEX];
|
||||
float viewportDiagonal = sqrtf(viewportWidth * viewportWidth + viewportHeight * viewportHeight);
|
||||
float worldDiagonal = glm::distance(Application::getInstance()->getDisplayViewFrustum()->getNearBottomLeft(),
|
||||
Application::getInstance()->getDisplayViewFrustum()->getNearTopRight());
|
||||
|
||||
_pointProgram.bind();
|
||||
_pointProgram.setUniformValue(_pointScaleLocation, viewportDiagonal *
|
||||
Application::getInstance()->getDisplayViewFrustum()->getNearClip() / worldDiagonal);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
BufferRenderVisitor pointRenderVisitor(Application::getInstance()->getMetavoxels()->getPointBufferAttribute());
|
||||
data.guide(pointRenderVisitor);
|
||||
|
||||
glDisable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
|
||||
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
_pointProgram.release();
|
||||
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glAlphaFunc(GL_EQUAL, 0.0f);
|
||||
|
@ -2994,8 +2840,6 @@ void DefaultMetavoxelRendererImplementation::loadSplatProgram(const char* type,
|
|||
program.release();
|
||||
}
|
||||
|
||||
ProgramObject DefaultMetavoxelRendererImplementation::_pointProgram;
|
||||
int DefaultMetavoxelRendererImplementation::_pointScaleLocation;
|
||||
ProgramObject DefaultMetavoxelRendererImplementation::_baseHeightfieldProgram;
|
||||
int DefaultMetavoxelRendererImplementation::_baseHeightScaleLocation;
|
||||
int DefaultMetavoxelRendererImplementation::_baseColorScaleLocation;
|
||||
|
@ -3007,55 +2851,10 @@ ProgramObject DefaultMetavoxelRendererImplementation::_splatVoxelProgram;
|
|||
DefaultMetavoxelRendererImplementation::SplatLocations DefaultMetavoxelRendererImplementation::_splatVoxelLocations;
|
||||
ProgramObject DefaultMetavoxelRendererImplementation::_voxelCursorProgram;
|
||||
|
||||
static void enableClipPlane(GLenum plane, float x, float y, float z, float w) {
|
||||
GLdouble coefficients[] = { x, y, z, w };
|
||||
glClipPlane(plane, coefficients);
|
||||
glEnable(plane);
|
||||
}
|
||||
|
||||
void ClippedRenderer::render(const glm::vec4& color, Mode mode, const glm::vec3& clipMinimum, float clipSize) {
|
||||
if (clipSize == 0.0f) {
|
||||
renderUnclipped(color, mode);
|
||||
return;
|
||||
}
|
||||
enableClipPlane(GL_CLIP_PLANE0, -1.0f, 0.0f, 0.0f, clipMinimum.x + clipSize);
|
||||
enableClipPlane(GL_CLIP_PLANE1, 1.0f, 0.0f, 0.0f, -clipMinimum.x);
|
||||
enableClipPlane(GL_CLIP_PLANE2, 0.0f, -1.0f, 0.0f, clipMinimum.y + clipSize);
|
||||
enableClipPlane(GL_CLIP_PLANE3, 0.0f, 1.0f, 0.0f, -clipMinimum.y);
|
||||
enableClipPlane(GL_CLIP_PLANE4, 0.0f, 0.0f, -1.0f, clipMinimum.z + clipSize);
|
||||
enableClipPlane(GL_CLIP_PLANE5, 0.0f, 0.0f, 1.0f, -clipMinimum.z);
|
||||
|
||||
renderUnclipped(color, mode);
|
||||
|
||||
glDisable(GL_CLIP_PLANE0);
|
||||
glDisable(GL_CLIP_PLANE1);
|
||||
glDisable(GL_CLIP_PLANE2);
|
||||
glDisable(GL_CLIP_PLANE3);
|
||||
glDisable(GL_CLIP_PLANE4);
|
||||
glDisable(GL_CLIP_PLANE5);
|
||||
}
|
||||
|
||||
SphereRenderer::SphereRenderer() {
|
||||
}
|
||||
|
||||
void SphereRenderer::render(const glm::vec4& color, Mode mode, const glm::vec3& clipMinimum, float clipSize) {
|
||||
if (clipSize == 0.0f) {
|
||||
renderUnclipped(color, mode);
|
||||
return;
|
||||
}
|
||||
// slight performance optimization: don't render if clip bounds are entirely within sphere
|
||||
Sphere* sphere = static_cast<Sphere*>(_spanner);
|
||||
Box clipBox(clipMinimum, clipMinimum + glm::vec3(clipSize, clipSize, clipSize));
|
||||
for (int i = 0; i < Box::VERTEX_COUNT; i++) {
|
||||
const float CLIP_PROPORTION = 0.95f;
|
||||
if (glm::distance(sphere->getTranslation(), clipBox.getVertex(i)) >= sphere->getScale() * CLIP_PROPORTION) {
|
||||
ClippedRenderer::render(color, mode, clipMinimum, clipSize);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SphereRenderer::renderUnclipped(const glm::vec4& color, Mode mode) {
|
||||
void SphereRenderer::render(const glm::vec4& color, Mode mode) {
|
||||
Sphere* sphere = static_cast<Sphere*>(_spanner);
|
||||
const QColor& ownColor = sphere->getColor();
|
||||
glColor4f(ownColor.redF() * color.r, ownColor.greenF() * color.g, ownColor.blueF() * color.b, ownColor.alphaF() * color.a);
|
||||
|
@ -3075,7 +2874,7 @@ void SphereRenderer::renderUnclipped(const glm::vec4& color, Mode mode) {
|
|||
CuboidRenderer::CuboidRenderer() {
|
||||
}
|
||||
|
||||
void CuboidRenderer::renderUnclipped(const glm::vec4& color, Mode mode) {
|
||||
void CuboidRenderer::render(const glm::vec4& color, Mode mode) {
|
||||
Cuboid* cuboid = static_cast<Cuboid*>(_spanner);
|
||||
const QColor& ownColor = cuboid->getColor();
|
||||
glColor4f(ownColor.redF() * color.r, ownColor.greenF() * color.g, ownColor.blueF() * color.b, ownColor.alphaF() * color.a);
|
||||
|
@ -3126,7 +2925,7 @@ void StaticModelRenderer::simulate(float deltaTime) {
|
|||
_model->simulate(deltaTime);
|
||||
}
|
||||
|
||||
void StaticModelRenderer::renderUnclipped(const glm::vec4& color, Mode mode) {
|
||||
void StaticModelRenderer::render(const glm::vec4& color, Mode mode) {
|
||||
switch (mode) {
|
||||
case DIFFUSE_MODE:
|
||||
_model->render(color.a, Model::DIFFUSE_RENDER_MODE);
|
||||
|
@ -3143,8 +2942,7 @@ void StaticModelRenderer::renderUnclipped(const glm::vec4& color, Mode mode) {
|
|||
_model->render(color.a);
|
||||
}
|
||||
|
||||
bool StaticModelRenderer::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const glm::vec3& clipMinimum, float clipSize, float& distance) const {
|
||||
bool StaticModelRenderer::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const {
|
||||
RayIntersectionInfo info;
|
||||
info._rayStart = origin;
|
||||
info._rayDirection = direction;
|
||||
|
|
|
@ -54,7 +54,6 @@ public:
|
|||
void setNetworkSimulation(const NetworkSimulation& simulation);
|
||||
NetworkSimulation getNetworkSimulation();
|
||||
|
||||
const AttributePointer& getPointBufferAttribute() { return _pointBufferAttribute; }
|
||||
const AttributePointer& getHeightfieldBufferAttribute() { return _heightfieldBufferAttribute; }
|
||||
const AttributePointer& getVoxelBufferAttribute() { return _voxelBufferAttribute; }
|
||||
|
||||
|
@ -103,7 +102,6 @@ private:
|
|||
|
||||
void guideToAugmented(MetavoxelVisitor& visitor, bool render = false);
|
||||
|
||||
AttributePointer _pointBufferAttribute;
|
||||
AttributePointer _heightfieldBufferAttribute;
|
||||
AttributePointer _voxelBufferAttribute;
|
||||
|
||||
|
@ -124,18 +122,6 @@ public slots:
|
|||
virtual void handle() = 0;
|
||||
};
|
||||
|
||||
/// Describes contents of a point in a point buffer.
|
||||
class BufferPoint {
|
||||
public:
|
||||
glm::vec4 vertex;
|
||||
quint8 color[3];
|
||||
quint8 normal[3];
|
||||
};
|
||||
|
||||
typedef QVector<BufferPoint> BufferPointVector;
|
||||
|
||||
Q_DECLARE_METATYPE(BufferPointVector)
|
||||
|
||||
/// Simple throttle for limiting bandwidth on a per-second basis.
|
||||
class Throttle {
|
||||
public:
|
||||
|
@ -203,21 +189,6 @@ public:
|
|||
|
||||
typedef QExplicitlySharedDataPointer<BufferData> BufferDataPointer;
|
||||
|
||||
/// Contains the information necessary to render a group of points.
|
||||
class PointBuffer : public BufferData {
|
||||
public:
|
||||
|
||||
PointBuffer(const BufferPointVector& points);
|
||||
|
||||
virtual void render(bool cursor = false);
|
||||
|
||||
private:
|
||||
|
||||
BufferPointVector _points;
|
||||
QOpenGLBuffer _buffer;
|
||||
int _pointCount;
|
||||
};
|
||||
|
||||
/// Contains the information necessary to render a heightfield block.
|
||||
class HeightfieldBuffer : public BufferData {
|
||||
public:
|
||||
|
@ -369,9 +340,6 @@ public:
|
|||
|
||||
static void init();
|
||||
|
||||
static ProgramObject& getPointProgram() { return _pointProgram; }
|
||||
static int getPointScaleLocation() { return _pointScaleLocation; }
|
||||
|
||||
static ProgramObject& getBaseHeightfieldProgram() { return _baseHeightfieldProgram; }
|
||||
static int getBaseHeightScaleLocation() { return _baseHeightScaleLocation; }
|
||||
static int getBaseColorScaleLocation() { return _baseColorScaleLocation; }
|
||||
|
@ -411,9 +379,6 @@ private:
|
|||
|
||||
static void loadSplatProgram(const char* type, ProgramObject& program, SplatLocations& locations);
|
||||
|
||||
static ProgramObject _pointProgram;
|
||||
static int _pointScaleLocation;
|
||||
|
||||
static ProgramObject _baseHeightfieldProgram;
|
||||
static int _baseHeightScaleLocation;
|
||||
static int _baseColorScaleLocation;
|
||||
|
@ -438,49 +403,30 @@ private:
|
|||
static ProgramObject _voxelCursorProgram;
|
||||
};
|
||||
|
||||
/// Base class for spanner renderers; provides clipping.
|
||||
class ClippedRenderer : public SpannerRenderer {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
virtual void render(const glm::vec4& color, Mode mode, const glm::vec3& clipMinimum, float clipSize);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void renderUnclipped(const glm::vec4& color, Mode mode) = 0;
|
||||
};
|
||||
|
||||
/// Renders spheres.
|
||||
class SphereRenderer : public ClippedRenderer {
|
||||
class SphereRenderer : public SpannerRenderer {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
Q_INVOKABLE SphereRenderer();
|
||||
|
||||
virtual void render(const glm::vec4& color, Mode mode, const glm::vec3& clipMinimum, float clipSize);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void renderUnclipped(const glm::vec4& color, Mode mode);
|
||||
virtual void render(const glm::vec4& color, Mode mode);
|
||||
};
|
||||
|
||||
/// Renders cuboids.
|
||||
class CuboidRenderer : public ClippedRenderer {
|
||||
class CuboidRenderer : public SpannerRenderer {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
Q_INVOKABLE CuboidRenderer();
|
||||
|
||||
protected:
|
||||
|
||||
virtual void renderUnclipped(const glm::vec4& color, Mode mode);
|
||||
virtual void render(const glm::vec4& color, Mode mode);
|
||||
};
|
||||
|
||||
/// Renders static models.
|
||||
class StaticModelRenderer : public ClippedRenderer {
|
||||
class StaticModelRenderer : public SpannerRenderer {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -489,12 +435,8 @@ public:
|
|||
|
||||
virtual void init(Spanner* spanner);
|
||||
virtual void simulate(float deltaTime);
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const glm::vec3& clipMinimum, float clipSize, float& distance) const;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void renderUnclipped(const glm::vec4& color, Mode mode);
|
||||
virtual void render(const glm::vec4& color, Mode mode);
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||
|
||||
private slots:
|
||||
|
||||
|
|
|
@ -122,7 +122,6 @@ MetavoxelEditor::MetavoxelEditor() :
|
|||
addTool(new InsertSpannerTool(this));
|
||||
addTool(new RemoveSpannerTool(this));
|
||||
addTool(new ClearSpannersTool(this));
|
||||
addTool(new SetSpannerTool(this));
|
||||
addTool(new HeightfieldHeightBrushTool(this));
|
||||
addTool(new HeightfieldMaterialBrushTool(this));
|
||||
addTool(new ImportHeightfieldTool(this));
|
||||
|
@ -241,7 +240,7 @@ void MetavoxelEditor::createNewAttribute() {
|
|||
form.addRow("Name:", &name);
|
||||
|
||||
SharedObjectEditor editor(&Attribute::staticMetaObject, false);
|
||||
editor.setObject(new QRgbAttribute());
|
||||
editor.setObject(new FloatAttribute());
|
||||
layout.addWidget(&editor);
|
||||
|
||||
QDialogButtonBox buttons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
|
@ -622,7 +621,7 @@ void PlaceSpannerTool::render() {
|
|||
const float SPANNER_ALPHA = 0.25f;
|
||||
QColor color = getColor();
|
||||
spanner->getRenderer()->render(glm::vec4(color.redF(), color.greenF(), color.blueF(), SPANNER_ALPHA),
|
||||
SpannerRenderer::DEFAULT_MODE, glm::vec3(), 0.0f);
|
||||
SpannerRenderer::DEFAULT_MODE);
|
||||
}
|
||||
|
||||
bool PlaceSpannerTool::appliesTo(const AttributePointer& attribute) const {
|
||||
|
@ -712,244 +711,6 @@ void ClearSpannersTool::clear() {
|
|||
Application::getInstance()->getMetavoxels()->applyEdit(message);
|
||||
}
|
||||
|
||||
SetSpannerTool::SetSpannerTool(MetavoxelEditor* editor) :
|
||||
PlaceSpannerTool(editor, "Set Spanner", "Set") {
|
||||
}
|
||||
|
||||
bool SetSpannerTool::appliesTo(const AttributePointer& attribute) const {
|
||||
return attribute == AttributeRegistry::getInstance()->getSpannersAttribute();
|
||||
}
|
||||
|
||||
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, float granularity, const QVector<DirectionImages>& directionImages);
|
||||
|
||||
virtual void run();
|
||||
|
||||
private:
|
||||
|
||||
void voxelize(const glm::vec3& center);
|
||||
|
||||
float _size;
|
||||
Box _bounds;
|
||||
float _granularity;
|
||||
QVector<DirectionImages> _directionImages;
|
||||
};
|
||||
|
||||
Voxelizer::Voxelizer(float size, const Box& bounds, float granularity, const QVector<DirectionImages>& directionImages) :
|
||||
_size(size),
|
||||
_bounds(bounds),
|
||||
_granularity(granularity),
|
||||
_directionImages(directionImages) {
|
||||
}
|
||||
|
||||
void Voxelizer::run() {
|
||||
// voxelize separately each cell within the bounds
|
||||
float halfSize = _size * 0.5f;
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, float extent) {
|
||||
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 >= -extent - EPSILON) {
|
||||
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);
|
||||
const float EXTENT_SCALE = 2.0f;
|
||||
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, extents.z * EXTENT_SCALE)) {
|
||||
info.outputValues[0] = AttributeValue(_outputs.at(0));
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
}
|
||||
return DEFAULT_ORDER;
|
||||
}
|
||||
QRgb closestColor = QRgb();
|
||||
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;
|
||||
float extent = images.scale.z * halfSize * EXTENT_SCALE;
|
||||
if (distance < -extent - EPSILON) {
|
||||
info.outputValues[0] = AttributeValue(_outputs.at(0));
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
QRgb color = images.color.pixel(x, y);
|
||||
if (distance < extent + 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);
|
||||
|
||||
VoxelizationVisitor visitor(_directionImages, center, _granularity);
|
||||
data.guide(visitor);
|
||||
|
||||
MetavoxelEditMessage edit = { QVariant::fromValue(SetDataEdit(
|
||||
center - glm::vec3(_size, _size, _size) * 0.5f, data, true)) };
|
||||
QMetaObject::invokeMethod(Application::getInstance()->getMetavoxels(), "applyEdit",
|
||||
Q_ARG(const MetavoxelEditMessage&, edit), Q_ARG(bool, true));
|
||||
}
|
||||
|
||||
void SetSpannerTool::applyEdit(const AttributePointer& attribute, const SharedObjectPointer& spanner) {
|
||||
Spanner* spannerData = static_cast<Spanner*>(spanner.data());
|
||||
Box bounds = spannerData->getBounds();
|
||||
float longestSide(qMax(bounds.getLongestSide(), spannerData->getPlacementGranularity()));
|
||||
float size = powf(2.0f, floorf(logf(longestSide) / logf(2.0f)));
|
||||
Box cellBounds(glm::floor(bounds.minimum / size) * size, glm::ceil(bounds.maximum / size) * size);
|
||||
|
||||
Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->bind();
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
|
||||
QVector<DirectionImages> directionImages;
|
||||
|
||||
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 = DIRECTION_ROTATIONS[i] * cellBounds.getVertex(j);
|
||||
minima = glm::min(minima, rotated);
|
||||
maxima = glm::max(maxima, rotated);
|
||||
}
|
||||
float renderGranularity = spannerData->getVoxelizationGranularity() / 4.0f;
|
||||
int width = glm::round((maxima.x - minima.x) / renderGranularity);
|
||||
int height = glm::round((maxima.y - minima.y) / renderGranularity);
|
||||
|
||||
glViewport(0, 0, width, height);
|
||||
glScissor(0, 0, width, height);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glLoadIdentity();
|
||||
glOrtho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
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();
|
||||
|
||||
Application::getInstance()->updateUntranslatedViewMatrix();
|
||||
|
||||
const glm::vec4 OPAQUE_WHITE(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
spannerData->getRenderer()->render(OPAQUE_WHITE, SpannerRenderer::DIFFUSE_MODE, glm::vec3(), 0.0f);
|
||||
|
||||
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);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
}
|
||||
glPopMatrix();
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->release();
|
||||
|
||||
glViewport(0, 0, Application::getInstance()->getGLWidget()->getDeviceWidth(),
|
||||
Application::getInstance()->getGLWidget()->getDeviceHeight());
|
||||
|
||||
// send the images off to the lab for processing
|
||||
QThreadPool::globalInstance()->start(new Voxelizer(size, cellBounds,
|
||||
spannerData->getVoxelizationGranularity(), directionImages));
|
||||
}
|
||||
|
||||
HeightfieldTool::HeightfieldTool(MetavoxelEditor* editor, const QString& name) :
|
||||
MetavoxelTool(editor, name, false) {
|
||||
|
||||
|
|
|
@ -242,21 +242,6 @@ private slots:
|
|||
void clear();
|
||||
};
|
||||
|
||||
/// Allows setting the value by placing a spanner.
|
||||
class SetSpannerTool : public PlaceSpannerTool {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
SetSpannerTool(MetavoxelEditor* editor);
|
||||
|
||||
virtual bool appliesTo(const AttributePointer& attribute) const;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void applyEdit(const AttributePointer& attribute, const SharedObjectPointer& spanner);
|
||||
};
|
||||
|
||||
/// Base class for heightfield tools.
|
||||
class HeightfieldTool : public MetavoxelTool {
|
||||
Q_OBJECT
|
||||
|
|
|
@ -19,10 +19,6 @@
|
|||
#include "MetavoxelData.h"
|
||||
|
||||
REGISTER_META_OBJECT(FloatAttribute)
|
||||
REGISTER_META_OBJECT(QRgbAttribute)
|
||||
REGISTER_META_OBJECT(PackedNormalAttribute)
|
||||
REGISTER_META_OBJECT(SpannerQRgbAttribute)
|
||||
REGISTER_META_OBJECT(SpannerPackedNormalAttribute)
|
||||
REGISTER_META_OBJECT(MaterialObject)
|
||||
REGISTER_META_OBJECT(HeightfieldAttribute)
|
||||
REGISTER_META_OBJECT(HeightfieldColorAttribute)
|
||||
|
@ -48,11 +44,6 @@ AttributeRegistry::AttributeRegistry() :
|
|||
_rendererAttribute(registerAttribute(new SharedObjectAttribute("renderer", &MetavoxelRenderer::staticMetaObject,
|
||||
new DefaultMetavoxelRenderer()))),
|
||||
_spannersAttribute(registerAttribute(new SpannerSetAttribute("spanners", &Spanner::staticMetaObject))),
|
||||
_colorAttribute(registerAttribute(new QRgbAttribute("color"))),
|
||||
_normalAttribute(registerAttribute(new PackedNormalAttribute("normal"))),
|
||||
_spannerColorAttribute(registerAttribute(new SpannerQRgbAttribute("spannerColor"))),
|
||||
_spannerNormalAttribute(registerAttribute(new SpannerPackedNormalAttribute("spannerNormal"))),
|
||||
_spannerMaskAttribute(registerAttribute(new FloatAttribute("spannerMask"))),
|
||||
_heightfieldAttribute(registerAttribute(new HeightfieldAttribute("heightfield"))),
|
||||
_heightfieldColorAttribute(registerAttribute(new HeightfieldColorAttribute("heightfieldColor"))),
|
||||
_heightfieldMaterialAttribute(registerAttribute(new HeightfieldMaterialAttribute("heightfieldMaterial"))),
|
||||
|
@ -89,8 +80,6 @@ static QScriptValue qDebugFunction(QScriptContext* context, QScriptEngine* engin
|
|||
|
||||
void AttributeRegistry::configureScriptEngine(QScriptEngine* engine) {
|
||||
QScriptValue registry = engine->newObject();
|
||||
registry.setProperty("colorAttribute", engine->newQObject(_colorAttribute.data()));
|
||||
registry.setProperty("normalAttribute", engine->newQObject(_normalAttribute.data()));
|
||||
registry.setProperty("getAttribute", engine->newFunction(getAttribute, 1));
|
||||
engine->globalObject().setProperty("AttributeRegistry", registry);
|
||||
engine->globalObject().setProperty("qDebug", engine->newFunction(qDebugFunction, 1));
|
||||
|
@ -292,111 +281,8 @@ MetavoxelNode* Attribute::expandMetavoxelRoot(const MetavoxelNode& root) {
|
|||
return newParent;
|
||||
}
|
||||
|
||||
FloatAttribute::FloatAttribute(const QString& name, float defaultValue) :
|
||||
SimpleInlineAttribute<float>(name, defaultValue) {
|
||||
}
|
||||
|
||||
QRgbAttribute::QRgbAttribute(const QString& name, QRgb defaultValue) :
|
||||
InlineAttribute<QRgb>(name, defaultValue) {
|
||||
}
|
||||
|
||||
bool QRgbAttribute::merge(void*& parent, void* children[], bool postRead) const {
|
||||
QRgb firstValue = decodeInline<QRgb>(children[0]);
|
||||
int totalAlpha = qAlpha(firstValue);
|
||||
int totalRed = qRed(firstValue) * totalAlpha;
|
||||
int totalGreen = qGreen(firstValue) * totalAlpha;
|
||||
int totalBlue = qBlue(firstValue) * totalAlpha;
|
||||
bool allChildrenEqual = true;
|
||||
for (int i = 1; i < Attribute::MERGE_COUNT; i++) {
|
||||
QRgb value = decodeInline<QRgb>(children[i]);
|
||||
int alpha = qAlpha(value);
|
||||
totalRed += qRed(value) * alpha;
|
||||
totalGreen += qGreen(value) * alpha;
|
||||
totalBlue += qBlue(value) * alpha;
|
||||
totalAlpha += alpha;
|
||||
allChildrenEqual &= (firstValue == value);
|
||||
}
|
||||
if (totalAlpha == 0) {
|
||||
parent = encodeInline(QRgb());
|
||||
} else {
|
||||
parent = encodeInline(qRgba(totalRed / totalAlpha, totalGreen / totalAlpha,
|
||||
totalBlue / totalAlpha, totalAlpha / MERGE_COUNT));
|
||||
}
|
||||
return allChildrenEqual;
|
||||
}
|
||||
|
||||
void* QRgbAttribute::mix(void* first, void* second, float alpha) const {
|
||||
QRgb firstValue = decodeInline<QRgb>(first);
|
||||
QRgb secondValue = decodeInline<QRgb>(second);
|
||||
return encodeInline(qRgba(
|
||||
glm::mix((float)qRed(firstValue), (float)qRed(secondValue), alpha),
|
||||
glm::mix((float)qGreen(firstValue), (float)qGreen(secondValue), alpha),
|
||||
glm::mix((float)qBlue(firstValue), (float)qBlue(secondValue), alpha),
|
||||
glm::mix((float)qAlpha(firstValue), (float)qAlpha(secondValue), alpha)));
|
||||
}
|
||||
|
||||
const float EIGHT_BIT_MAXIMUM = 255.0f;
|
||||
|
||||
void* QRgbAttribute::blend(void* source, void* dest) const {
|
||||
QRgb sourceValue = decodeInline<QRgb>(source);
|
||||
QRgb destValue = decodeInline<QRgb>(dest);
|
||||
float alpha = qAlpha(sourceValue) / EIGHT_BIT_MAXIMUM;
|
||||
return encodeInline(qRgba(
|
||||
glm::mix((float)qRed(destValue), (float)qRed(sourceValue), alpha),
|
||||
glm::mix((float)qGreen(destValue), (float)qGreen(sourceValue), alpha),
|
||||
glm::mix((float)qBlue(destValue), (float)qBlue(sourceValue), alpha),
|
||||
glm::mix((float)qAlpha(destValue), (float)qAlpha(sourceValue), alpha)));
|
||||
}
|
||||
|
||||
void* QRgbAttribute::createFromScript(const QScriptValue& value, QScriptEngine* engine) const {
|
||||
return encodeInline((QRgb)value.toUInt32());
|
||||
}
|
||||
|
||||
void* QRgbAttribute::createFromVariant(const QVariant& value) const {
|
||||
switch (value.userType()) {
|
||||
case QMetaType::QColor:
|
||||
return encodeInline(value.value<QColor>().rgba());
|
||||
|
||||
default:
|
||||
return encodeInline((QRgb)value.toUInt());
|
||||
}
|
||||
}
|
||||
|
||||
QWidget* QRgbAttribute::createEditor(QWidget* parent) const {
|
||||
QColorEditor* editor = new QColorEditor(parent);
|
||||
editor->setColor(QColor::fromRgba(_defaultValue));
|
||||
return editor;
|
||||
}
|
||||
|
||||
PackedNormalAttribute::PackedNormalAttribute(const QString& name, QRgb defaultValue) :
|
||||
QRgbAttribute(name, defaultValue) {
|
||||
}
|
||||
|
||||
bool PackedNormalAttribute::merge(void*& parent, void* children[], bool postRead) const {
|
||||
QRgb firstValue = decodeInline<QRgb>(children[0]);
|
||||
glm::vec3 total = unpackNormal(firstValue) * (float)qAlpha(firstValue);
|
||||
bool allChildrenEqual = true;
|
||||
for (int i = 1; i < Attribute::MERGE_COUNT; i++) {
|
||||
QRgb value = decodeInline<QRgb>(children[i]);
|
||||
total += unpackNormal(value) * (float)qAlpha(value);
|
||||
allChildrenEqual &= (firstValue == value);
|
||||
}
|
||||
float length = glm::length(total);
|
||||
parent = encodeInline(length < EPSILON ? QRgb() : packNormal(total / length));
|
||||
return allChildrenEqual;
|
||||
}
|
||||
|
||||
void* PackedNormalAttribute::mix(void* first, void* second, float alpha) const {
|
||||
glm::vec3 firstNormal = unpackNormal(decodeInline<QRgb>(first));
|
||||
glm::vec3 secondNormal = unpackNormal(decodeInline<QRgb>(second));
|
||||
return encodeInline(packNormal(glm::normalize(glm::mix(firstNormal, secondNormal, alpha))));
|
||||
}
|
||||
|
||||
void* PackedNormalAttribute::blend(void* source, void* dest) const {
|
||||
QRgb sourceValue = decodeInline<QRgb>(source);
|
||||
QRgb destValue = decodeInline<QRgb>(dest);
|
||||
float alpha = qAlpha(sourceValue) / EIGHT_BIT_MAXIMUM;
|
||||
return encodeInline(packNormal(glm::normalize(glm::mix(unpackNormal(destValue), unpackNormal(sourceValue), alpha))));
|
||||
FloatAttribute::FloatAttribute(const QString& name) :
|
||||
SimpleInlineAttribute(name) {
|
||||
}
|
||||
|
||||
const float CHAR_SCALE = 127.0f;
|
||||
|
@ -415,106 +301,6 @@ glm::vec3 unpackNormal(QRgb value) {
|
|||
(char)qBlue(value) * INVERSE_CHAR_SCALE);
|
||||
}
|
||||
|
||||
SpannerQRgbAttribute::SpannerQRgbAttribute(const QString& name, QRgb defaultValue) :
|
||||
QRgbAttribute(name, defaultValue) {
|
||||
}
|
||||
|
||||
void SpannerQRgbAttribute::read(Bitstream& in, void*& value, bool isLeaf) const {
|
||||
value = getDefaultValue();
|
||||
in.read(&value, 32);
|
||||
}
|
||||
|
||||
void SpannerQRgbAttribute::write(Bitstream& out, void* value, bool isLeaf) const {
|
||||
out.write(&value, 32);
|
||||
}
|
||||
|
||||
MetavoxelNode* SpannerQRgbAttribute::createMetavoxelNode(
|
||||
const AttributeValue& value, const MetavoxelNode* original) const {
|
||||
return new MetavoxelNode(value, original);
|
||||
}
|
||||
|
||||
bool SpannerQRgbAttribute::merge(void*& parent, void* children[], bool postRead) const {
|
||||
if (postRead) {
|
||||
for (int i = 0; i < MERGE_COUNT; i++) {
|
||||
if (qAlpha(decodeInline<QRgb>(children[i])) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
QRgb parentValue = decodeInline<QRgb>(parent);
|
||||
int totalAlpha = qAlpha(parentValue) * Attribute::MERGE_COUNT;
|
||||
int totalRed = qRed(parentValue) * totalAlpha;
|
||||
int totalGreen = qGreen(parentValue) * totalAlpha;
|
||||
int totalBlue = qBlue(parentValue) * totalAlpha;
|
||||
bool allChildrenTransparent = true;
|
||||
for (int i = 0; i < Attribute::MERGE_COUNT; i++) {
|
||||
QRgb value = decodeInline<QRgb>(children[i]);
|
||||
int alpha = qAlpha(value);
|
||||
totalRed += qRed(value) * alpha;
|
||||
totalGreen += qGreen(value) * alpha;
|
||||
totalBlue += qBlue(value) * alpha;
|
||||
totalAlpha += alpha;
|
||||
allChildrenTransparent &= (alpha == 0);
|
||||
}
|
||||
if (totalAlpha == 0) {
|
||||
parent = encodeInline(QRgb());
|
||||
} else {
|
||||
parent = encodeInline(qRgba(totalRed / totalAlpha, totalGreen / totalAlpha,
|
||||
totalBlue / totalAlpha, totalAlpha / MERGE_COUNT));
|
||||
}
|
||||
return allChildrenTransparent;
|
||||
}
|
||||
|
||||
AttributeValue SpannerQRgbAttribute::inherit(const AttributeValue& parentValue) const {
|
||||
return AttributeValue(parentValue.getAttribute());
|
||||
}
|
||||
|
||||
SpannerPackedNormalAttribute::SpannerPackedNormalAttribute(const QString& name, QRgb defaultValue) :
|
||||
PackedNormalAttribute(name, defaultValue) {
|
||||
}
|
||||
|
||||
void SpannerPackedNormalAttribute::read(Bitstream& in, void*& value, bool isLeaf) const {
|
||||
value = getDefaultValue();
|
||||
in.read(&value, 32);
|
||||
}
|
||||
|
||||
void SpannerPackedNormalAttribute::write(Bitstream& out, void* value, bool isLeaf) const {
|
||||
out.write(&value, 32);
|
||||
}
|
||||
|
||||
MetavoxelNode* SpannerPackedNormalAttribute::createMetavoxelNode(
|
||||
const AttributeValue& value, const MetavoxelNode* original) const {
|
||||
return new MetavoxelNode(value, original);
|
||||
}
|
||||
|
||||
bool SpannerPackedNormalAttribute::merge(void*& parent, void* children[], bool postRead) const {
|
||||
if (postRead) {
|
||||
for (int i = 0; i < MERGE_COUNT; i++) {
|
||||
if (qAlpha(decodeInline<QRgb>(children[i])) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
QRgb parentValue = decodeInline<QRgb>(parent);
|
||||
glm::vec3 total = unpackNormal(parentValue) * (float)(qAlpha(parentValue) * Attribute::MERGE_COUNT);
|
||||
bool allChildrenTransparent = true;
|
||||
for (int i = 0; i < Attribute::MERGE_COUNT; i++) {
|
||||
QRgb value = decodeInline<QRgb>(children[i]);
|
||||
int alpha = qAlpha(value);
|
||||
total += unpackNormal(value) * (float)alpha;
|
||||
allChildrenTransparent &= (alpha == 0);
|
||||
}
|
||||
float length = glm::length(total);
|
||||
parent = encodeInline(length < EPSILON ? QRgb() : packNormal(total / length));
|
||||
return allChildrenTransparent;
|
||||
}
|
||||
|
||||
AttributeValue SpannerPackedNormalAttribute::inherit(const AttributeValue& parentValue) const {
|
||||
return AttributeValue(parentValue.getAttribute());
|
||||
}
|
||||
|
||||
DataBlock::~DataBlock() {
|
||||
}
|
||||
|
||||
|
@ -1426,6 +1212,8 @@ static QHash<uchar, int> countIndices(const QByteArray& contents) {
|
|||
return counts;
|
||||
}
|
||||
|
||||
const float EIGHT_BIT_MAXIMUM = 255.0f;
|
||||
|
||||
uchar getMaterialIndex(const SharedObjectPointer& material, QVector<SharedObjectPointer>& materials, QByteArray& contents) {
|
||||
if (!(material && static_cast<MaterialObject*>(material.data())->getDiffuse().isValid())) {
|
||||
return 0;
|
||||
|
|
|
@ -88,21 +88,6 @@ public:
|
|||
/// Returns a reference to the standard SharedObjectSet "spanners" attribute.
|
||||
const AttributePointer& getSpannersAttribute() const { return _spannersAttribute; }
|
||||
|
||||
/// Returns a reference to the standard QRgb "color" attribute.
|
||||
const AttributePointer& getColorAttribute() const { return _colorAttribute; }
|
||||
|
||||
/// Returns a reference to the standard packed normal "normal" attribute.
|
||||
const AttributePointer& getNormalAttribute() const { return _normalAttribute; }
|
||||
|
||||
/// Returns a reference to the standard QRgb "spannerColor" attribute.
|
||||
const AttributePointer& getSpannerColorAttribute() const { return _spannerColorAttribute; }
|
||||
|
||||
/// Returns a reference to the standard packed normal "spannerNormal" attribute.
|
||||
const AttributePointer& getSpannerNormalAttribute() const { return _spannerNormalAttribute; }
|
||||
|
||||
/// Returns a reference to the standard "spannerMask" attribute.
|
||||
const AttributePointer& getSpannerMaskAttribute() const { return _spannerMaskAttribute; }
|
||||
|
||||
/// Returns a reference to the standard HeightfieldHeightDataPointer "heightfield" attribute.
|
||||
const AttributePointer& getHeightfieldAttribute() const { return _heightfieldAttribute; }
|
||||
|
||||
|
@ -131,11 +116,6 @@ private:
|
|||
AttributePointer _guideAttribute;
|
||||
AttributePointer _rendererAttribute;
|
||||
AttributePointer _spannersAttribute;
|
||||
AttributePointer _colorAttribute;
|
||||
AttributePointer _normalAttribute;
|
||||
AttributePointer _spannerColorAttribute;
|
||||
AttributePointer _spannerNormalAttribute;
|
||||
AttributePointer _spannerMaskAttribute;
|
||||
AttributePointer _heightfieldAttribute;
|
||||
AttributePointer _heightfieldColorAttribute;
|
||||
AttributePointer _heightfieldMaterialAttribute;
|
||||
|
@ -366,51 +346,13 @@ template<class T, int bits> inline bool SimpleInlineAttribute<T, bits>::merge(
|
|||
return allChildrenEqual;
|
||||
}
|
||||
|
||||
/// Simple float attribute.
|
||||
/// A simple float attribute.
|
||||
class FloatAttribute : public SimpleInlineAttribute<float> {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(float defaultValue MEMBER _defaultValue)
|
||||
|
||||
|
||||
public:
|
||||
|
||||
Q_INVOKABLE FloatAttribute(const QString& name = QString(), float defaultValue = 0.0f);
|
||||
};
|
||||
|
||||
/// Provides appropriate averaging for RGBA values.
|
||||
class QRgbAttribute : public InlineAttribute<QRgb> {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(uint defaultValue MEMBER _defaultValue)
|
||||
|
||||
public:
|
||||
|
||||
Q_INVOKABLE QRgbAttribute(const QString& name = QString(), QRgb defaultValue = QRgb());
|
||||
|
||||
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
|
||||
|
||||
virtual void* mix(void* first, void* second, float alpha) const;
|
||||
|
||||
virtual void* blend(void* source, void* dest) const;
|
||||
|
||||
virtual void* createFromScript(const QScriptValue& value, QScriptEngine* engine) const;
|
||||
|
||||
virtual void* createFromVariant(const QVariant& value) const;
|
||||
|
||||
virtual QWidget* createEditor(QWidget* parent = NULL) const;
|
||||
};
|
||||
|
||||
/// Provides appropriate averaging for packed normals.
|
||||
class PackedNormalAttribute : public QRgbAttribute {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
Q_INVOKABLE PackedNormalAttribute(const QString& name = QString(), QRgb defaultValue = QRgb());
|
||||
|
||||
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
|
||||
|
||||
virtual void* mix(void* first, void* second, float alpha) const;
|
||||
|
||||
virtual void* blend(void* source, void* dest) const;
|
||||
Q_INVOKABLE FloatAttribute(const QString& name = QString());
|
||||
};
|
||||
|
||||
/// Packs a normal into an RGB value.
|
||||
|
@ -422,42 +364,6 @@ QRgb packNormal(const glm::vec3& normal, int alpha);
|
|||
/// Unpacks a normal from an RGB value.
|
||||
glm::vec3 unpackNormal(QRgb value);
|
||||
|
||||
/// RGBA values for voxelized spanners.
|
||||
class SpannerQRgbAttribute : public QRgbAttribute {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
Q_INVOKABLE SpannerQRgbAttribute(const QString& name = QString(), QRgb defaultValue = QRgb());
|
||||
|
||||
virtual void read(Bitstream& in, void*& value, bool isLeaf) const;
|
||||
virtual void write(Bitstream& out, void* value, bool isLeaf) const;
|
||||
|
||||
virtual MetavoxelNode* createMetavoxelNode(const AttributeValue& value, const MetavoxelNode* original) const;
|
||||
|
||||
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
|
||||
|
||||
virtual AttributeValue inherit(const AttributeValue& parentValue) const;
|
||||
};
|
||||
|
||||
/// Packed normals for voxelized spanners.
|
||||
class SpannerPackedNormalAttribute : public PackedNormalAttribute {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
Q_INVOKABLE SpannerPackedNormalAttribute(const QString& name = QString(), QRgb defaultValue = QRgb());
|
||||
|
||||
virtual void read(Bitstream& in, void*& value, bool isLeaf) const;
|
||||
virtual void write(Bitstream& out, void* value, bool isLeaf) const;
|
||||
|
||||
virtual MetavoxelNode* createMetavoxelNode(const AttributeValue& value, const MetavoxelNode* original) const;
|
||||
|
||||
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
|
||||
|
||||
virtual AttributeValue inherit(const AttributeValue& parentValue) const;
|
||||
};
|
||||
|
||||
typedef QExplicitlySharedDataPointer<DataBlock> DataBlockPointer;
|
||||
|
||||
/// Base class for blocks of data.
|
||||
|
|
|
@ -63,19 +63,6 @@ SharedObjectPointer MetavoxelClientManager::findFirstRaySpannerIntersection(cons
|
|||
return closestSpanner;
|
||||
}
|
||||
|
||||
void MetavoxelClientManager::setSphere(const glm::vec3& center, float radius, const QColor& color) {
|
||||
Sphere* sphere = new Sphere();
|
||||
sphere->setTranslation(center);
|
||||
sphere->setScale(radius);
|
||||
sphere->setColor(color);
|
||||
setSpanner(sphere);
|
||||
}
|
||||
|
||||
void MetavoxelClientManager::setSpanner(const SharedObjectPointer& object, bool reliable) {
|
||||
MetavoxelEditMessage edit = { QVariant::fromValue(SetSpannerEdit(object)) };
|
||||
applyEdit(edit, reliable);
|
||||
}
|
||||
|
||||
void MetavoxelClientManager::paintHeightfieldHeight(const glm::vec3& position, float radius, float height) {
|
||||
MetavoxelEditMessage edit = { QVariant::fromValue(PaintHeightfieldHeightEdit(position, radius, height)) };
|
||||
applyEdit(edit, true);
|
||||
|
|
|
@ -37,10 +37,6 @@ public:
|
|||
SharedObjectPointer findFirstRaySpannerIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const AttributePointer& attribute, float& distance);
|
||||
|
||||
Q_INVOKABLE void setSphere(const glm::vec3& center, float radius, const QColor& color = QColor(Qt::gray));
|
||||
|
||||
Q_INVOKABLE void setSpanner(const SharedObjectPointer& object, bool reliable = false);
|
||||
|
||||
Q_INVOKABLE void paintHeightfieldHeight(const glm::vec3& position, float radius, float height);
|
||||
|
||||
Q_INVOKABLE void applyEdit(const MetavoxelEditMessage& edit, bool reliable = false);
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
|
||||
#include <QDateTime>
|
||||
#include <QDebugStateSaver>
|
||||
#include <QScriptEngine>
|
||||
#include <QThread>
|
||||
#include <QtDebug>
|
||||
|
||||
|
@ -21,12 +20,9 @@
|
|||
|
||||
#include "MetavoxelData.h"
|
||||
#include "MetavoxelUtil.h"
|
||||
#include "ScriptCache.h"
|
||||
|
||||
REGISTER_META_OBJECT(MetavoxelGuide)
|
||||
REGISTER_META_OBJECT(DefaultMetavoxelGuide)
|
||||
REGISTER_META_OBJECT(ScriptedMetavoxelGuide)
|
||||
REGISTER_META_OBJECT(ThrobbingMetavoxelGuide)
|
||||
REGISTER_META_OBJECT(MetavoxelRenderer)
|
||||
REGISTER_META_OBJECT(DefaultMetavoxelRenderer)
|
||||
REGISTER_META_OBJECT(Spanner)
|
||||
|
@ -401,7 +397,7 @@ private:
|
|||
FirstRaySpannerIntersectionVisitor::FirstRaySpannerIntersectionVisitor(
|
||||
const glm::vec3& origin, const glm::vec3& direction, const AttributePointer& attribute, const MetavoxelLOD& lod) :
|
||||
RaySpannerIntersectionVisitor(origin, direction, QVector<AttributePointer>() << attribute,
|
||||
QVector<AttributePointer>(), QVector<AttributePointer>(), QVector<AttributePointer>(), lod),
|
||||
QVector<AttributePointer>(), QVector<AttributePointer>(), lod),
|
||||
_spanner(NULL) {
|
||||
}
|
||||
|
||||
|
@ -714,6 +710,7 @@ bool MetavoxelData::deepEquals(const MetavoxelData& other, const MetavoxelLOD& l
|
|||
return false;
|
||||
}
|
||||
if (_roots.size() != other._roots.size()) {
|
||||
qDebug() << _roots << other._roots;
|
||||
return false;
|
||||
}
|
||||
glm::vec3 minimum = getMinimum();
|
||||
|
@ -1367,12 +1364,10 @@ MetavoxelVisitation& MetavoxelVisitor::acquireVisitation() {
|
|||
return _visitations[_depth];
|
||||
}
|
||||
|
||||
SpannerVisitor::SpannerVisitor(const QVector<AttributePointer>& spannerInputs, const QVector<AttributePointer>& spannerMasks,
|
||||
const QVector<AttributePointer>& inputs, const QVector<AttributePointer>& outputs,
|
||||
const MetavoxelLOD& lod, int order) :
|
||||
MetavoxelVisitor(inputs + spannerInputs + spannerMasks, outputs, lod),
|
||||
SpannerVisitor::SpannerVisitor(const QVector<AttributePointer>& spannerInputs, const QVector<AttributePointer>& inputs,
|
||||
const QVector<AttributePointer>& outputs, const MetavoxelLOD& lod, int order) :
|
||||
MetavoxelVisitor(inputs + spannerInputs, outputs, lod),
|
||||
_spannerInputCount(spannerInputs.size()),
|
||||
_spannerMaskCount(spannerMasks.size()),
|
||||
_order(order) {
|
||||
}
|
||||
|
||||
|
@ -1382,34 +1377,15 @@ void SpannerVisitor::prepare(MetavoxelData* data) {
|
|||
}
|
||||
|
||||
int SpannerVisitor::visit(MetavoxelInfo& info) {
|
||||
for (int end = _inputs.size() - _spannerMaskCount, i = end - _spannerInputCount, j = end; i < end; i++, j++) {
|
||||
for (int end = _inputs.size(), i = end - _spannerInputCount; i < end; i++) {
|
||||
foreach (const SharedObjectPointer& object, info.inputValues.at(i).getInlineValue<SharedObjectSet>()) {
|
||||
Spanner* spanner = static_cast<Spanner*>(object.data());
|
||||
if (!(spanner->isMasked() && j < _inputs.size()) && spanner->testAndSetVisited(_visit) &&
|
||||
!visit(spanner, glm::vec3(), 0.0f)) {
|
||||
if (spanner->testAndSetVisited(_visit) && !visit(spanner)) {
|
||||
return SHORT_CIRCUIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!info.isLeaf) {
|
||||
return _order;
|
||||
}
|
||||
for (int i = _inputs.size() - _spannerMaskCount; i < _inputs.size(); i++) {
|
||||
float maskValue = info.inputValues.at(i).getInlineValue<float>();
|
||||
if (maskValue < 0.5f) {
|
||||
const MetavoxelInfo* nextInfo = &info;
|
||||
do {
|
||||
foreach (const SharedObjectPointer& object, nextInfo->inputValues.at(
|
||||
i - _spannerInputCount).getInlineValue<SharedObjectSet>()) {
|
||||
Spanner* spanner = static_cast<Spanner*>(object.data());
|
||||
if (spanner->isMasked() && !visit(spanner, info.minimum, info.size)) {
|
||||
return SHORT_CIRCUIT;
|
||||
}
|
||||
}
|
||||
} while ((nextInfo = nextInfo->parentInfo));
|
||||
}
|
||||
}
|
||||
return STOP_RECURSION;
|
||||
return info.isLeaf ? STOP_RECURSION : _order;
|
||||
}
|
||||
|
||||
RayIntersectionVisitor::RayIntersectionVisitor(const glm::vec3& origin, const glm::vec3& direction,
|
||||
|
@ -1429,11 +1405,10 @@ int RayIntersectionVisitor::visit(MetavoxelInfo& info) {
|
|||
}
|
||||
|
||||
RaySpannerIntersectionVisitor::RaySpannerIntersectionVisitor(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const QVector<AttributePointer>& spannerInputs, const QVector<AttributePointer>& spannerMasks,
|
||||
const QVector<AttributePointer>& inputs, const QVector<AttributePointer>& outputs, const MetavoxelLOD& lod) :
|
||||
RayIntersectionVisitor(origin, direction, inputs + spannerInputs + spannerMasks, outputs, lod),
|
||||
_spannerInputCount(spannerInputs.size()),
|
||||
_spannerMaskCount(spannerMasks.size()) {
|
||||
const QVector<AttributePointer>& spannerInputs, const QVector<AttributePointer>& inputs,
|
||||
const QVector<AttributePointer>& outputs, const MetavoxelLOD& lod) :
|
||||
RayIntersectionVisitor(origin, direction, inputs + spannerInputs, outputs, lod),
|
||||
_spannerInputCount(spannerInputs.size()) {
|
||||
}
|
||||
|
||||
void RaySpannerIntersectionVisitor::prepare(MetavoxelData* data) {
|
||||
|
@ -1453,12 +1428,12 @@ bool operator<(const SpannerDistance& first, const SpannerDistance& second) {
|
|||
|
||||
int RaySpannerIntersectionVisitor::visit(MetavoxelInfo& info, float distance) {
|
||||
QVarLengthArray<SpannerDistance, 4> spannerDistances;
|
||||
for (int end = _inputs.size() - _spannerMaskCount, i = end - _spannerInputCount, j = end; i < end; i++, j++) {
|
||||
for (int end = _inputs.size(), i = end - _spannerInputCount; i < end; i++) {
|
||||
foreach (const SharedObjectPointer& object, info.inputValues.at(i).getInlineValue<SharedObjectSet>()) {
|
||||
Spanner* spanner = static_cast<Spanner*>(object.data());
|
||||
if (!(spanner->isMasked() && j < _inputs.size()) && spanner->testAndSetVisited(_visit)) {
|
||||
if (spanner->testAndSetVisited(_visit)) {
|
||||
SpannerDistance spannerDistance = { spanner };
|
||||
if (spanner->findRayIntersection(_origin, _direction, glm::vec3(), 0.0f, spannerDistance.distance)) {
|
||||
if (spanner->findRayIntersection(_origin, _direction, spannerDistance.distance)) {
|
||||
spannerDistances.append(spannerDistance);
|
||||
}
|
||||
}
|
||||
|
@ -1470,36 +1445,7 @@ int RaySpannerIntersectionVisitor::visit(MetavoxelInfo& info, float distance) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!info.isLeaf) {
|
||||
return _order;
|
||||
}
|
||||
for (int i = _inputs.size() - _spannerMaskCount; i < _inputs.size(); i++) {
|
||||
float maskValue = info.inputValues.at(i).getInlineValue<float>();
|
||||
if (maskValue < 0.5f) {
|
||||
const MetavoxelInfo* nextInfo = &info;
|
||||
do {
|
||||
foreach (const SharedObjectPointer& object, nextInfo->inputValues.at(
|
||||
i - _spannerInputCount).getInlineValue<SharedObjectSet>()) {
|
||||
Spanner* spanner = static_cast<Spanner*>(object.data());
|
||||
if (spanner->isMasked()) {
|
||||
SpannerDistance spannerDistance = { spanner };
|
||||
if (spanner->findRayIntersection(_origin, _direction,
|
||||
info.minimum, info.size, spannerDistance.distance)) {
|
||||
spannerDistances.append(spannerDistance);
|
||||
}
|
||||
}
|
||||
}
|
||||
} while ((nextInfo = nextInfo->parentInfo));
|
||||
|
||||
qStableSort(spannerDistances);
|
||||
foreach (const SpannerDistance& spannerDistance, spannerDistances) {
|
||||
if (!visitSpanner(spannerDistance.spanner, spannerDistance.distance)) {
|
||||
return SHORT_CIRCUIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return STOP_RECURSION;
|
||||
return info.isLeaf ? STOP_RECURSION : _order;
|
||||
}
|
||||
|
||||
bool MetavoxelGuide::guideToDifferent(MetavoxelVisitation& visitation) {
|
||||
|
@ -1765,143 +1711,6 @@ bool DefaultMetavoxelGuide::guideToDifferent(MetavoxelVisitation& visitation) {
|
|||
return true;
|
||||
}
|
||||
|
||||
ThrobbingMetavoxelGuide::ThrobbingMetavoxelGuide() : _rate(10.0) {
|
||||
}
|
||||
|
||||
bool ThrobbingMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
||||
AttributePointer colorAttribute = AttributeRegistry::getInstance()->getColorAttribute();
|
||||
for (int i = 0; i < visitation.info.inputValues.size(); i++) {
|
||||
AttributeValue& attributeValue = visitation.info.inputValues[i];
|
||||
if (attributeValue.getAttribute() == colorAttribute) {
|
||||
QRgb base = attributeValue.getInlineValue<QRgb>();
|
||||
double seconds = QDateTime::currentMSecsSinceEpoch() / 1000.0;
|
||||
double amplitude = sin(_rate * seconds) * 0.5 + 0.5;
|
||||
attributeValue.setInlineValue<QRgb>(qRgba(qRed(base) * amplitude, qGreen(base) * amplitude,
|
||||
qBlue(base) * amplitude, qAlpha(base)));
|
||||
}
|
||||
}
|
||||
|
||||
return DefaultMetavoxelGuide::guide(visitation);
|
||||
}
|
||||
|
||||
static QScriptValue getAttributes(QScriptEngine* engine, ScriptedMetavoxelGuide* guide,
|
||||
const QVector<AttributePointer>& attributes) {
|
||||
|
||||
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*>());
|
||||
|
||||
// start with the basics, including inherited attribute values
|
||||
QScriptValue infoValue = context->argument(0);
|
||||
QScriptValue minimum = infoValue.property(guide->_minimumHandle);
|
||||
MetavoxelInfo info(NULL, 0, 0);
|
||||
info.inputValues = guide->_visitation->info.inputValues;
|
||||
info.outputValues = guide->_visitation->info.outputValues;
|
||||
info.minimum = glm::vec3(minimum.property(0).toNumber(), minimum.property(1).toNumber(), minimum.property(2).toNumber());
|
||||
info.size = (float)infoValue.property(guide->_sizeHandle).toNumber();
|
||||
info.isLeaf = infoValue.property(guide->_isLeafHandle).toBool();
|
||||
|
||||
// extract and convert the values provided by the script
|
||||
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.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 < inputs.size(); i++) {
|
||||
if (inputValues.property(i).isValid()) {
|
||||
info.inputValues[i].getAttribute()->destroy(info.inputValues[i].getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ScriptedMetavoxelGuide::ScriptedMetavoxelGuide() {
|
||||
}
|
||||
|
||||
bool ScriptedMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
||||
QScriptValue guideFunction;
|
||||
if (_guideFunction) {
|
||||
guideFunction = _guideFunction->getValue();
|
||||
|
||||
} else if (_url.isValid()) {
|
||||
_guideFunction = ScriptCache::getInstance()->getValue(_url);
|
||||
guideFunction = _guideFunction->getValue();
|
||||
}
|
||||
if (!guideFunction.isValid()) {
|
||||
// before we load, just use the default behavior
|
||||
return DefaultMetavoxelGuide::guide(visitation);
|
||||
}
|
||||
QScriptEngine* engine = guideFunction.engine();
|
||||
if (!_minimumHandle.isValid()) {
|
||||
_minimumHandle = engine->toStringHandle("minimum");
|
||||
_sizeHandle = engine->toStringHandle("size");
|
||||
_inputValuesHandle = engine->toStringHandle("inputValues");
|
||||
_outputValuesHandle = engine->toStringHandle("outputValues");
|
||||
_isLeafHandle = engine->toStringHandle("isLeaf");
|
||||
_getInputsFunction = engine->newFunction(getInputs, 0);
|
||||
_getOutputsFunction = engine->newFunction(getOutputs, 0);
|
||||
_visitFunction = engine->newFunction(visit, 1);
|
||||
_info = engine->newObject();
|
||||
_minimum = engine->newArray(3);
|
||||
|
||||
_arguments.clear();
|
||||
_arguments.append(engine->newObject());
|
||||
QScriptValue visitor = engine->newObject();
|
||||
visitor.setProperty("getInputs", _getInputsFunction);
|
||||
visitor.setProperty("getOutputs", _getOutputsFunction);
|
||||
visitor.setProperty("visit", _visitFunction);
|
||||
_arguments[0].setProperty("visitor", visitor);
|
||||
_arguments[0].setProperty("info", _info);
|
||||
_info.setProperty(_minimumHandle, _minimum);
|
||||
}
|
||||
QScriptValue data = engine->newVariant(QVariant::fromValue<void*>(this));
|
||||
_getInputsFunction.setData(data);
|
||||
_visitFunction.setData(data);
|
||||
_minimum.setProperty(0, visitation.info.minimum.x);
|
||||
_minimum.setProperty(1, visitation.info.minimum.y);
|
||||
_minimum.setProperty(2, visitation.info.minimum.z);
|
||||
_info.setProperty(_sizeHandle, visitation.info.size);
|
||||
_info.setProperty(_isLeafHandle, visitation.info.isLeaf);
|
||||
_visitation = &visitation;
|
||||
guideFunction.call(QScriptValue(), _arguments);
|
||||
if (engine->hasUncaughtException()) {
|
||||
qDebug() << "Script error: " << engine->uncaughtException().toString();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScriptedMetavoxelGuide::setURL(const ParameterizedURL& url) {
|
||||
_url = url;
|
||||
_guideFunction.reset();
|
||||
_minimumHandle = QScriptString();
|
||||
}
|
||||
|
||||
MetavoxelVisitation::MetavoxelVisitation(MetavoxelVisitation* previous,
|
||||
MetavoxelVisitor* visitor, int inputNodesSize, int outputNodesSize) :
|
||||
previous(previous),
|
||||
|
@ -1997,8 +1806,7 @@ const float DEFAULT_VOXELIZATION_GRANULARITY = powf(2.0f, -3.0f);
|
|||
Spanner::Spanner() :
|
||||
_renderer(NULL),
|
||||
_placementGranularity(DEFAULT_PLACEMENT_GRANULARITY),
|
||||
_voxelizationGranularity(DEFAULT_VOXELIZATION_GRANULARITY),
|
||||
_masked(false) {
|
||||
_voxelizationGranularity(DEFAULT_VOXELIZATION_GRANULARITY) {
|
||||
}
|
||||
|
||||
void Spanner::setBounds(const Box& bounds) {
|
||||
|
@ -2009,24 +1817,6 @@ void Spanner::setBounds(const Box& bounds) {
|
|||
emit boundsChanged(_bounds = bounds);
|
||||
}
|
||||
|
||||
const QVector<AttributePointer>& Spanner::getAttributes() const {
|
||||
static QVector<AttributePointer> emptyVector;
|
||||
return emptyVector;
|
||||
}
|
||||
|
||||
const QVector<AttributePointer>& Spanner::getVoxelizedAttributes() const {
|
||||
static QVector<AttributePointer> emptyVector;
|
||||
return emptyVector;
|
||||
}
|
||||
|
||||
bool Spanner::getAttributeValues(MetavoxelInfo& info, bool force) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Spanner::blendAttributeValues(MetavoxelInfo& info, bool force) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Spanner::testAndSetVisited(int visit) {
|
||||
QMutexLocker locker(&_lastVisitsMutex);
|
||||
int& lastVisit = _lastVisits[QThread::currentThread()];
|
||||
|
@ -2052,8 +1842,7 @@ SpannerRenderer* Spanner::getRenderer() {
|
|||
return _renderer;
|
||||
}
|
||||
|
||||
bool Spanner::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const glm::vec3& clipMinimum, float clipSize, float& distance) const {
|
||||
bool Spanner::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const {
|
||||
return _bounds.findRayIntersection(origin, direction, distance);
|
||||
}
|
||||
|
||||
|
@ -2103,12 +1892,11 @@ void SpannerRenderer::simulate(float deltaTime) {
|
|||
// nothing by default
|
||||
}
|
||||
|
||||
void SpannerRenderer::render(const glm::vec4& color, Mode mode, const glm::vec3& clipMinimum, float clipSize) {
|
||||
void SpannerRenderer::render(const glm::vec4& color, Mode mode) {
|
||||
// nothing by default
|
||||
}
|
||||
|
||||
bool SpannerRenderer::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const glm::vec3& clipMinimum, float clipSize, float& distance) const {
|
||||
bool SpannerRenderer::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2149,92 +1937,7 @@ Sphere::Sphere() {
|
|||
updateBounds();
|
||||
}
|
||||
|
||||
const QVector<AttributePointer>& Sphere::getAttributes() const {
|
||||
static QVector<AttributePointer> attributes = QVector<AttributePointer>() <<
|
||||
AttributeRegistry::getInstance()->getColorAttribute() << AttributeRegistry::getInstance()->getNormalAttribute();
|
||||
return attributes;
|
||||
}
|
||||
|
||||
const QVector<AttributePointer>& Sphere::getVoxelizedAttributes() const {
|
||||
static QVector<AttributePointer> attributes = QVector<AttributePointer>() <<
|
||||
AttributeRegistry::getInstance()->getSpannerColorAttribute() <<
|
||||
AttributeRegistry::getInstance()->getSpannerNormalAttribute();
|
||||
return attributes;
|
||||
}
|
||||
|
||||
bool Sphere::getAttributeValues(MetavoxelInfo& info, bool force) const {
|
||||
// bounds check
|
||||
Box bounds = info.getBounds();
|
||||
if (!(force || getBounds().intersects(bounds))) {
|
||||
return false;
|
||||
}
|
||||
// count the points inside the sphere
|
||||
int pointsWithin = 0;
|
||||
for (int i = 0; i < Box::VERTEX_COUNT; i++) {
|
||||
if (glm::distance(bounds.getVertex(i), getTranslation()) <= getScale()) {
|
||||
pointsWithin++;
|
||||
}
|
||||
}
|
||||
if (pointsWithin == Box::VERTEX_COUNT) {
|
||||
// entirely contained
|
||||
info.outputValues[0] = AttributeValue(getAttributes().at(0), encodeInline<QRgb>(_color.rgba()));
|
||||
info.outputValues[1] = getNormal(info, _color.alpha());
|
||||
return false;
|
||||
}
|
||||
if (force || info.size <= getVoxelizationGranularity()) {
|
||||
// best guess
|
||||
if (pointsWithin > 0) {
|
||||
int alpha = _color.alpha() * pointsWithin / Box::VERTEX_COUNT;
|
||||
info.outputValues[0] = AttributeValue(getAttributes().at(0), encodeInline<QRgb>(qRgba(
|
||||
_color.red(), _color.green(), _color.blue(), alpha)));
|
||||
info.outputValues[1] = getNormal(info, alpha);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sphere::blendAttributeValues(MetavoxelInfo& info, bool force) const {
|
||||
// bounds check
|
||||
Box bounds = info.getBounds();
|
||||
if (!(force || getBounds().intersects(bounds))) {
|
||||
return false;
|
||||
}
|
||||
// count the points inside the sphere
|
||||
int pointsWithin = 0;
|
||||
for (int i = 0; i < Box::VERTEX_COUNT; i++) {
|
||||
if (glm::distance(bounds.getVertex(i), getTranslation()) <= getScale()) {
|
||||
pointsWithin++;
|
||||
}
|
||||
}
|
||||
if (pointsWithin == Box::VERTEX_COUNT) {
|
||||
// entirely contained
|
||||
info.outputValues[0] = AttributeValue(getAttributes().at(0), encodeInline<QRgb>(_color.rgba()));
|
||||
info.outputValues[1] = getNormal(info, _color.alpha());
|
||||
return false;
|
||||
}
|
||||
if (force || info.size <= getVoxelizationGranularity()) {
|
||||
// best guess
|
||||
if (pointsWithin > 0) {
|
||||
const AttributeValue& oldColor = info.outputValues.at(0).getAttribute() ?
|
||||
info.outputValues.at(0) : info.inputValues.at(0);
|
||||
const AttributeValue& oldNormal = info.outputValues.at(1).getAttribute() ?
|
||||
info.outputValues.at(1) : info.inputValues.at(1);
|
||||
int oldAlpha = qAlpha(oldColor.getInlineValue<QRgb>());
|
||||
int newAlpha = _color.alpha() * pointsWithin / Box::VERTEX_COUNT;
|
||||
float combinedAlpha = (float)newAlpha / (oldAlpha + newAlpha);
|
||||
int baseAlpha = _color.alpha() * pointsWithin / Box::VERTEX_COUNT;
|
||||
info.outputValues[0].mix(oldColor, AttributeValue(getAttributes().at(0),
|
||||
encodeInline<QRgb>(qRgba(_color.red(), _color.green(), _color.blue(), baseAlpha))), combinedAlpha);
|
||||
info.outputValues[1].mix(oldNormal, getNormal(info, baseAlpha), combinedAlpha);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sphere::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const glm::vec3& clipMinimum, float clipSize, float& distance) const {
|
||||
bool Sphere::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const {
|
||||
return findRaySphereIntersection(origin, direction, getTranslation(), getScale(), distance);
|
||||
}
|
||||
|
||||
|
@ -2279,23 +1982,6 @@ void Sphere::updateBounds() {
|
|||
setBounds(Box(getTranslation() - extent, getTranslation() + extent));
|
||||
}
|
||||
|
||||
AttributeValue Sphere::getNormal(MetavoxelInfo& info, int alpha) const {
|
||||
glm::vec3 normal = info.getCenter() - getTranslation();
|
||||
float length = glm::length(normal);
|
||||
QRgb color;
|
||||
if (alpha != 0 && length > EPSILON) {
|
||||
const float NORMAL_SCALE = 127.0f;
|
||||
float scale = NORMAL_SCALE / length;
|
||||
const int BYTE_MASK = 0xFF;
|
||||
color = qRgba((int)(normal.x * scale) & BYTE_MASK, (int)(normal.y * scale) & BYTE_MASK,
|
||||
(int)(normal.z * scale) & BYTE_MASK, alpha);
|
||||
|
||||
} else {
|
||||
color = QRgb();
|
||||
}
|
||||
return AttributeValue(getAttributes().at(1), encodeInline<QRgb>(color));
|
||||
}
|
||||
|
||||
Cuboid::Cuboid() :
|
||||
_aspectY(1.0f),
|
||||
_aspectZ(1.0f) {
|
||||
|
@ -2388,11 +2074,10 @@ void StaticModel::setURL(const QUrl& url) {
|
|||
}
|
||||
}
|
||||
|
||||
bool StaticModel::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const glm::vec3& clipMinimum, float clipSize, float& distance) const {
|
||||
bool StaticModel::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const {
|
||||
// delegate to renderer, if we have one
|
||||
return _renderer ? _renderer->findRayIntersection(origin, direction, clipMinimum, clipSize, distance) :
|
||||
Spanner::findRayIntersection(origin, direction, clipMinimum, clipSize, distance);
|
||||
return _renderer ? _renderer->findRayIntersection(origin, direction, distance) :
|
||||
Spanner::findRayIntersection(origin, direction, distance);
|
||||
}
|
||||
|
||||
QByteArray StaticModel::getRendererClassName() const {
|
||||
|
|
|
@ -12,13 +12,10 @@
|
|||
#ifndef hifi_MetavoxelData_h
|
||||
#define hifi_MetavoxelData_h
|
||||
|
||||
#include <QBitArray>
|
||||
#include <QHash>
|
||||
#include <QMutex>
|
||||
#include <QSharedData>
|
||||
#include <QSharedPointer>
|
||||
#include <QScriptString>
|
||||
#include <QScriptValue>
|
||||
#include <QVector>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
@ -26,8 +23,6 @@
|
|||
#include "AttributeRegistry.h"
|
||||
#include "MetavoxelUtil.h"
|
||||
|
||||
class QScriptContext;
|
||||
|
||||
class MetavoxelInfo;
|
||||
class MetavoxelNode;
|
||||
class MetavoxelRendererImplementation;
|
||||
|
@ -373,16 +368,14 @@ class SpannerVisitor : public MetavoxelVisitor {
|
|||
public:
|
||||
|
||||
SpannerVisitor(const QVector<AttributePointer>& spannerInputs,
|
||||
const QVector<AttributePointer>& spannerMasks = QVector<AttributePointer>(),
|
||||
const QVector<AttributePointer>& inputs = QVector<AttributePointer>(),
|
||||
const QVector<AttributePointer>& outputs = QVector<AttributePointer>(),
|
||||
const MetavoxelLOD& lod = MetavoxelLOD(),
|
||||
int order = DEFAULT_ORDER);
|
||||
|
||||
/// Visits a spanner (or part thereof).
|
||||
/// \param clipSize the size of the clip volume, or zero if unclipped
|
||||
/// Visits a spanner.
|
||||
/// \return true to continue, false to short-circuit the tour
|
||||
virtual bool visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize) = 0;
|
||||
virtual bool visit(Spanner* spanner) = 0;
|
||||
|
||||
virtual void prepare(MetavoxelData* data);
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
|
@ -390,7 +383,6 @@ public:
|
|||
protected:
|
||||
|
||||
int _spannerInputCount;
|
||||
int _spannerMaskCount;
|
||||
int _order;
|
||||
int _visit;
|
||||
};
|
||||
|
@ -422,12 +414,11 @@ public:
|
|||
|
||||
RaySpannerIntersectionVisitor(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const QVector<AttributePointer>& spannerInputs,
|
||||
const QVector<AttributePointer>& spannerMasks = QVector<AttributePointer>(),
|
||||
const QVector<AttributePointer>& inputs = QVector<AttributePointer>(),
|
||||
const QVector<AttributePointer>& outputs = QVector<AttributePointer>(),
|
||||
const MetavoxelLOD& lod = MetavoxelLOD());
|
||||
|
||||
/// Visits a spannerthat the ray intersects.
|
||||
/// Visits a spanner that the ray intersects.
|
||||
/// \return true to continue, false to short-circuit the tour
|
||||
virtual bool visitSpanner(Spanner* spanner, float distance) = 0;
|
||||
|
||||
|
@ -437,7 +428,6 @@ public:
|
|||
protected:
|
||||
|
||||
int _spannerInputCount;
|
||||
int _spannerMaskCount;
|
||||
int _visit;
|
||||
};
|
||||
|
||||
|
@ -468,62 +458,6 @@ public:
|
|||
virtual bool guideToDifferent(MetavoxelVisitation& visitation);
|
||||
};
|
||||
|
||||
/// A temporary test guide that just makes the existing voxels throb with delight.
|
||||
class ThrobbingMetavoxelGuide : public DefaultMetavoxelGuide {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(float rate MEMBER _rate)
|
||||
|
||||
public:
|
||||
|
||||
Q_INVOKABLE ThrobbingMetavoxelGuide();
|
||||
|
||||
virtual bool guide(MetavoxelVisitation& visitation);
|
||||
|
||||
private:
|
||||
|
||||
float _rate;
|
||||
};
|
||||
|
||||
/// Represents a guide implemented in Javascript.
|
||||
class ScriptedMetavoxelGuide : public DefaultMetavoxelGuide {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(ParameterizedURL url MEMBER _url WRITE setURL)
|
||||
|
||||
public:
|
||||
|
||||
Q_INVOKABLE ScriptedMetavoxelGuide();
|
||||
|
||||
virtual bool guide(MetavoxelVisitation& visitation);
|
||||
|
||||
public slots:
|
||||
|
||||
void setURL(const ParameterizedURL& url);
|
||||
|
||||
private:
|
||||
|
||||
static QScriptValue getInputs(QScriptContext* context, QScriptEngine* engine);
|
||||
static QScriptValue getOutputs(QScriptContext* context, QScriptEngine* engine);
|
||||
static QScriptValue visit(QScriptContext* context, QScriptEngine* engine);
|
||||
|
||||
ParameterizedURL _url;
|
||||
|
||||
QSharedPointer<NetworkValue> _guideFunction;
|
||||
|
||||
QScriptString _minimumHandle;
|
||||
QScriptString _sizeHandle;
|
||||
QScriptString _inputValuesHandle;
|
||||
QScriptString _outputValuesHandle;
|
||||
QScriptString _isLeafHandle;
|
||||
QScriptValueList _arguments;
|
||||
QScriptValue _getInputsFunction;
|
||||
QScriptValue _getOutputsFunction;
|
||||
QScriptValue _visitFunction;
|
||||
QScriptValue _info;
|
||||
QScriptValue _minimum;
|
||||
|
||||
MetavoxelVisitation* _visitation;
|
||||
};
|
||||
|
||||
/// Contains the state associated with a visit to a metavoxel system.
|
||||
class MetavoxelVisitation {
|
||||
public:
|
||||
|
@ -598,7 +532,6 @@ class Spanner : public SharedObject {
|
|||
Q_PROPERTY(Box bounds MEMBER _bounds WRITE setBounds NOTIFY boundsChanged DESIGNABLE false)
|
||||
Q_PROPERTY(float placementGranularity MEMBER _placementGranularity DESIGNABLE false)
|
||||
Q_PROPERTY(float voxelizationGranularity MEMBER _voxelizationGranularity DESIGNABLE false)
|
||||
Q_PROPERTY(float masked MEMBER _masked DESIGNABLE false)
|
||||
|
||||
public:
|
||||
|
||||
|
@ -616,24 +549,6 @@ public:
|
|||
void setVoxelizationGranularity(float granularity) { _voxelizationGranularity = granularity; }
|
||||
float getVoxelizationGranularity() const { return _voxelizationGranularity; }
|
||||
|
||||
void setMasked(bool masked) { _masked = masked; }
|
||||
bool isMasked() const { return _masked; }
|
||||
|
||||
/// Returns a reference to the list of attributes associated with this spanner.
|
||||
virtual const QVector<AttributePointer>& getAttributes() const;
|
||||
|
||||
/// Returns a reference to the list of corresponding attributes that we voxelize the spanner into.
|
||||
virtual const QVector<AttributePointer>& getVoxelizedAttributes() const;
|
||||
|
||||
/// Sets the attribute values associated with this spanner in the supplied info.
|
||||
/// \return true to recurse, false to stop
|
||||
virtual bool getAttributeValues(MetavoxelInfo& info, bool force = false) const;
|
||||
|
||||
/// Blends the attribute values associated with this spanner into the supplied info.
|
||||
/// \param force if true, blend even if we would normally subdivide
|
||||
/// \return true to recurse, false to stop
|
||||
virtual bool blendAttributeValues(MetavoxelInfo& info, bool force = false) const;
|
||||
|
||||
/// Checks whether we've visited this object on the current traversal. If we have, returns false.
|
||||
/// If we haven't, sets the last visit identifier and returns true.
|
||||
bool testAndSetVisited(int visit);
|
||||
|
@ -642,9 +557,7 @@ public:
|
|||
SpannerRenderer* getRenderer();
|
||||
|
||||
/// Finds the intersection between the described ray and this spanner.
|
||||
/// \param clipSize the size of the clip region, or zero if unclipped
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const glm::vec3& clipMinimum, float clipSize, float& distance) const;
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||
|
||||
/// Checks whether this spanner has its own colors.
|
||||
virtual bool hasOwnColors() const;
|
||||
|
@ -684,7 +597,6 @@ private:
|
|||
Box _bounds;
|
||||
float _placementGranularity;
|
||||
float _voxelizationGranularity;
|
||||
bool _masked;
|
||||
QHash<QThread*, int> _lastVisits; ///< last visit identifiers for each thread
|
||||
QMutex _lastVisitsMutex;
|
||||
|
||||
|
@ -703,9 +615,8 @@ public:
|
|||
|
||||
virtual void init(Spanner* spanner);
|
||||
virtual void simulate(float deltaTime);
|
||||
virtual void render(const glm::vec4& color, Mode mode, const glm::vec3& clipMinimum, float clipSize);
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const glm::vec3& clipMinimum, float clipSize, float& distance) const;
|
||||
virtual void render(const glm::vec4& color, Mode mode);
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -774,12 +685,7 @@ public:
|
|||
|
||||
Q_INVOKABLE Sphere();
|
||||
|
||||
virtual const QVector<AttributePointer>& getAttributes() const;
|
||||
virtual const QVector<AttributePointer>& getVoxelizedAttributes() const;
|
||||
virtual bool getAttributeValues(MetavoxelInfo& info, bool force = false) const;
|
||||
virtual bool blendAttributeValues(MetavoxelInfo& info, bool force = false) const;
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const glm::vec3& clipMinimum, float clipSize, float& distance) const;
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||
virtual bool contains(const glm::vec3& point);
|
||||
virtual bool intersects(const glm::vec3& start, const glm::vec3& end, float& distance, glm::vec3& normal);
|
||||
|
||||
|
@ -790,10 +696,6 @@ protected:
|
|||
private slots:
|
||||
|
||||
void updateBounds();
|
||||
|
||||
private:
|
||||
|
||||
AttributeValue getNormal(MetavoxelInfo& info, int alpha) const;
|
||||
};
|
||||
|
||||
/// A cuboid.
|
||||
|
@ -849,8 +751,7 @@ public:
|
|||
void setURL(const QUrl& url);
|
||||
const QUrl& getURL() const { return _url; }
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const glm::vec3& clipMinimum, float clipSize, float& distance) const;
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||
|
||||
signals:
|
||||
|
||||
|
|
|
@ -39,8 +39,7 @@ private:
|
|||
};
|
||||
|
||||
BoxSetEditVisitor::BoxSetEditVisitor(const BoxSetEdit& edit) :
|
||||
MetavoxelVisitor(QVector<AttributePointer>(), QVector<AttributePointer>() << edit.value.getAttribute() <<
|
||||
AttributeRegistry::getInstance()->getSpannerMaskAttribute()),
|
||||
MetavoxelVisitor(QVector<AttributePointer>(), QVector<AttributePointer>() << edit.value.getAttribute()),
|
||||
_edit(edit) {
|
||||
}
|
||||
|
||||
|
@ -55,57 +54,17 @@ int BoxSetEditVisitor::visit(MetavoxelInfo& info) {
|
|||
float volume = (size.x * size.y * size.z) / (info.size * info.size * info.size);
|
||||
if (volume >= 1.0f) {
|
||||
info.outputValues[0] = _edit.value;
|
||||
info.outputValues[1] = AttributeValue(_outputs.at(1), encodeInline<float>(1.0f));
|
||||
return STOP_RECURSION; // entirely contained
|
||||
}
|
||||
if (info.size <= _edit.granularity) {
|
||||
if (volume >= 0.5f) {
|
||||
info.outputValues[0] = _edit.value;
|
||||
info.outputValues[1] = AttributeValue(_outputs.at(1), encodeInline<float>(1.0f));
|
||||
}
|
||||
return STOP_RECURSION; // reached granularity limit; take best guess
|
||||
}
|
||||
return DEFAULT_ORDER; // subdivide
|
||||
}
|
||||
|
||||
class GatherUnmaskedSpannersVisitor : public SpannerVisitor {
|
||||
public:
|
||||
|
||||
GatherUnmaskedSpannersVisitor(const Box& bounds);
|
||||
|
||||
const QList<SharedObjectPointer>& getUnmaskedSpanners() const { return _unmaskedSpanners; }
|
||||
|
||||
virtual bool visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize);
|
||||
|
||||
private:
|
||||
|
||||
Box _bounds;
|
||||
QList<SharedObjectPointer> _unmaskedSpanners;
|
||||
};
|
||||
|
||||
GatherUnmaskedSpannersVisitor::GatherUnmaskedSpannersVisitor(const Box& bounds) :
|
||||
SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute()),
|
||||
_bounds(bounds) {
|
||||
}
|
||||
|
||||
bool GatherUnmaskedSpannersVisitor::visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize) {
|
||||
if (!spanner->isMasked() && spanner->getBounds().intersects(_bounds)) {
|
||||
_unmaskedSpanners.append(spanner);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void setIntersectingMasked(const Box& bounds, MetavoxelData& data) {
|
||||
GatherUnmaskedSpannersVisitor visitor(bounds);
|
||||
data.guide(visitor);
|
||||
|
||||
foreach (const SharedObjectPointer& object, visitor.getUnmaskedSpanners()) {
|
||||
Spanner* newSpanner = static_cast<Spanner*>(object->clone(true));
|
||||
newSpanner->setMasked(true);
|
||||
data.replace(AttributeRegistry::getInstance()->getSpannersAttribute(), object, newSpanner);
|
||||
}
|
||||
}
|
||||
|
||||
void BoxSetEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
||||
// expand to fit the entire edit
|
||||
while (!data.getBounds().contains(region)) {
|
||||
|
@ -114,9 +73,6 @@ void BoxSetEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects)
|
|||
|
||||
BoxSetEditVisitor setVisitor(*this);
|
||||
data.guide(setVisitor);
|
||||
|
||||
// flip the mask flag of all intersecting spanners
|
||||
setIntersectingMasked(region, data);
|
||||
}
|
||||
|
||||
GlobalSetEdit::GlobalSetEdit(const OwnedAttributeValue& value) :
|
||||
|
@ -155,56 +111,8 @@ InsertSpannerEdit::InsertSpannerEdit(const AttributePointer& attribute, const Sh
|
|||
spanner(spanner) {
|
||||
}
|
||||
|
||||
class UpdateSpannerVisitor : public MetavoxelVisitor {
|
||||
public:
|
||||
|
||||
UpdateSpannerVisitor(const QVector<AttributePointer>& attributes, Spanner* spanner);
|
||||
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
|
||||
private:
|
||||
|
||||
Spanner* _spanner;
|
||||
float _voxelizationSize;
|
||||
int _steps;
|
||||
};
|
||||
|
||||
UpdateSpannerVisitor::UpdateSpannerVisitor(const QVector<AttributePointer>& attributes, Spanner* spanner) :
|
||||
MetavoxelVisitor(QVector<AttributePointer>() << attributes << AttributeRegistry::getInstance()->getSpannersAttribute(),
|
||||
attributes),
|
||||
_spanner(spanner),
|
||||
_voxelizationSize(qMax(spanner->getBounds().getLongestSide(), spanner->getPlacementGranularity()) * 2.0f /
|
||||
AttributeRegistry::getInstance()->getSpannersAttribute()->getLODThresholdMultiplier()),
|
||||
_steps(glm::round(logf(AttributeRegistry::getInstance()->getSpannersAttribute()->getLODThresholdMultiplier()) /
|
||||
logf(2.0f) - 2.0f)) {
|
||||
}
|
||||
|
||||
int UpdateSpannerVisitor::visit(MetavoxelInfo& info) {
|
||||
if (!info.getBounds().intersects(_spanner->getBounds())) {
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
MetavoxelInfo* parentInfo = info.parentInfo;
|
||||
for (int i = 0; i < _steps && parentInfo; i++) {
|
||||
parentInfo = parentInfo->parentInfo;
|
||||
}
|
||||
for (int i = 0; i < _outputs.size(); i++) {
|
||||
info.outputValues[i] = AttributeValue(_outputs.at(i));
|
||||
}
|
||||
if (parentInfo) {
|
||||
foreach (const SharedObjectPointer& object,
|
||||
parentInfo->inputValues.at(_outputs.size()).getInlineValue<SharedObjectSet>()) {
|
||||
static_cast<const Spanner*>(object.data())->blendAttributeValues(info, true);
|
||||
}
|
||||
}
|
||||
return (info.size > _voxelizationSize) ? DEFAULT_ORDER : STOP_RECURSION;
|
||||
}
|
||||
|
||||
void InsertSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
||||
data.insert(attribute, this->spanner);
|
||||
|
||||
Spanner* spanner = static_cast<Spanner*>(this->spanner.data());
|
||||
UpdateSpannerVisitor visitor(spanner->getVoxelizedAttributes(), spanner);
|
||||
data.guide(visitor);
|
||||
data.insert(attribute, spanner);
|
||||
}
|
||||
|
||||
RemoveSpannerEdit::RemoveSpannerEdit(const AttributePointer& attribute, int id) :
|
||||
|
@ -218,99 +126,15 @@ void RemoveSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& o
|
|||
qDebug() << "Missing object to remove" << id;
|
||||
return;
|
||||
}
|
||||
// keep a strong reference to the object
|
||||
SharedObjectPointer sharedPointer = object;
|
||||
data.remove(attribute, object);
|
||||
|
||||
Spanner* spanner = static_cast<Spanner*>(object);
|
||||
UpdateSpannerVisitor visitor(spanner->getVoxelizedAttributes(), spanner);
|
||||
data.guide(visitor);
|
||||
}
|
||||
|
||||
ClearSpannersEdit::ClearSpannersEdit(const AttributePointer& attribute) :
|
||||
attribute(attribute) {
|
||||
}
|
||||
|
||||
class GatherSpannerAttributesVisitor : public SpannerVisitor {
|
||||
public:
|
||||
|
||||
GatherSpannerAttributesVisitor(const AttributePointer& attribute);
|
||||
|
||||
const QSet<AttributePointer>& getAttributes() const { return _attributes; }
|
||||
|
||||
virtual bool visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize);
|
||||
|
||||
protected:
|
||||
|
||||
QSet<AttributePointer> _attributes;
|
||||
};
|
||||
|
||||
GatherSpannerAttributesVisitor::GatherSpannerAttributesVisitor(const AttributePointer& attribute) :
|
||||
SpannerVisitor(QVector<AttributePointer>() << attribute) {
|
||||
}
|
||||
|
||||
bool GatherSpannerAttributesVisitor::visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize) {
|
||||
foreach (const AttributePointer& attribute, spanner->getVoxelizedAttributes()) {
|
||||
_attributes.insert(attribute);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClearSpannersEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
||||
// find all the spanner attributes
|
||||
GatherSpannerAttributesVisitor visitor(attribute);
|
||||
data.guide(visitor);
|
||||
|
||||
data.clear(attribute);
|
||||
foreach (const AttributePointer& attribute, visitor.getAttributes()) {
|
||||
data.clear(attribute);
|
||||
}
|
||||
}
|
||||
|
||||
SetSpannerEdit::SetSpannerEdit(const SharedObjectPointer& spanner) :
|
||||
spanner(spanner) {
|
||||
}
|
||||
|
||||
class SetSpannerEditVisitor : public MetavoxelVisitor {
|
||||
public:
|
||||
|
||||
SetSpannerEditVisitor(const QVector<AttributePointer>& attributes, Spanner* spanner);
|
||||
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
|
||||
private:
|
||||
|
||||
Spanner* _spanner;
|
||||
};
|
||||
|
||||
SetSpannerEditVisitor::SetSpannerEditVisitor(const QVector<AttributePointer>& attributes, Spanner* spanner) :
|
||||
MetavoxelVisitor(attributes, QVector<AttributePointer>() << attributes <<
|
||||
AttributeRegistry::getInstance()->getSpannerMaskAttribute()),
|
||||
_spanner(spanner) {
|
||||
}
|
||||
|
||||
int SetSpannerEditVisitor::visit(MetavoxelInfo& info) {
|
||||
if (_spanner->blendAttributeValues(info)) {
|
||||
return DEFAULT_ORDER;
|
||||
}
|
||||
if (info.outputValues.at(0).getAttribute()) {
|
||||
info.outputValues.last() = AttributeValue(_outputs.last(), encodeInline<float>(1.0f));
|
||||
}
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
|
||||
void SetSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
||||
Spanner* spanner = static_cast<Spanner*>(this->spanner.data());
|
||||
|
||||
// expand to fit the entire spanner
|
||||
while (!data.getBounds().contains(spanner->getBounds())) {
|
||||
data.expand();
|
||||
}
|
||||
|
||||
SetSpannerEditVisitor visitor(spanner->getAttributes(), spanner);
|
||||
data.guide(visitor);
|
||||
|
||||
setIntersectingMasked(spanner->getBounds(), data);
|
||||
}
|
||||
|
||||
SetDataEdit::SetDataEdit(const glm::vec3& minimum, const MetavoxelData& data, bool blend) :
|
||||
|
|
|
@ -177,21 +177,6 @@ public:
|
|||
|
||||
DECLARE_STREAMABLE_METATYPE(ClearSpannersEdit)
|
||||
|
||||
/// An edit that sets a spanner's attributes in the voxel tree.
|
||||
class SetSpannerEdit : public MetavoxelEdit {
|
||||
STREAMABLE
|
||||
|
||||
public:
|
||||
|
||||
STREAM SharedObjectPointer spanner;
|
||||
|
||||
SetSpannerEdit(const SharedObjectPointer& spanner = SharedObjectPointer());
|
||||
|
||||
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
||||
};
|
||||
|
||||
DECLARE_STREAMABLE_METATYPE(SetSpannerEdit)
|
||||
|
||||
/// An edit that directly sets part of the metavoxel data.
|
||||
class SetDataEdit : public MetavoxelEdit {
|
||||
STREAMABLE
|
||||
|
|
|
@ -439,12 +439,17 @@ static bool testSerialization(Bitstream::MetadataType metadataType) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static AttributePointer simpleAttribute;
|
||||
|
||||
bool MetavoxelTests::run() {
|
||||
LimitedNodeList::createInstance();
|
||||
|
||||
// seed the random number generator so that our tests are reproducible
|
||||
srand(0xBAAAAABE);
|
||||
|
||||
// register our test attribute
|
||||
simpleAttribute = AttributeRegistry::getInstance()->registerAttribute(new FloatAttribute("simpleAttribute"));
|
||||
|
||||
// check for an optional command line argument specifying a single test
|
||||
QStringList arguments = this->arguments();
|
||||
int test = (arguments.size() > 1) ? arguments.at(1).toInt() : 0;
|
||||
|
@ -582,8 +587,7 @@ public:
|
|||
};
|
||||
|
||||
RandomVisitor::RandomVisitor() :
|
||||
MetavoxelVisitor(QVector<AttributePointer>(),
|
||||
QVector<AttributePointer>() << AttributeRegistry::getInstance()->getColorAttribute()),
|
||||
MetavoxelVisitor(QVector<AttributePointer>(), QVector<AttributePointer>() << simpleAttribute),
|
||||
leafCount(0) {
|
||||
}
|
||||
|
||||
|
@ -594,8 +598,7 @@ int RandomVisitor::visit(MetavoxelInfo& info) {
|
|||
if (info.size > MAXIMUM_LEAF_SIZE || (info.size > MINIMUM_LEAF_SIZE && randomBoolean())) {
|
||||
return DEFAULT_ORDER;
|
||||
}
|
||||
info.outputValues[0] = OwnedAttributeValue(_outputs.at(0), encodeInline<QRgb>(qRgb(randomColorValue(),
|
||||
randomColorValue(), randomColorValue())));
|
||||
info.outputValues[0] = OwnedAttributeValue(_outputs.at(0), encodeInline<float>(randFloat()));
|
||||
leafCount++;
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
|
@ -812,8 +815,7 @@ private:
|
|||
};
|
||||
|
||||
MutateVisitor::MutateVisitor() :
|
||||
MetavoxelVisitor(QVector<AttributePointer>(),
|
||||
QVector<AttributePointer>() << AttributeRegistry::getInstance()->getColorAttribute()),
|
||||
MetavoxelVisitor(QVector<AttributePointer>(), QVector<AttributePointer>() << simpleAttribute),
|
||||
_mutationsRemaining(randIntInRange(2, 4)) {
|
||||
}
|
||||
|
||||
|
@ -824,8 +826,7 @@ int MutateVisitor::visit(MetavoxelInfo& info) {
|
|||
if (info.size > MAXIMUM_LEAF_SIZE || (info.size > MINIMUM_LEAF_SIZE && randomBoolean())) {
|
||||
return encodeRandomOrder();
|
||||
}
|
||||
info.outputValues[0] = OwnedAttributeValue(_outputs.at(0), encodeInline<QRgb>(qRgb(randomColorValue(),
|
||||
randomColorValue(), randomColorValue())));
|
||||
info.outputValues[0] = OwnedAttributeValue(_outputs.at(0), encodeInline<float>(randFloat()));
|
||||
_mutationsRemaining--;
|
||||
metavoxelMutationsPerformed++;
|
||||
return STOP_RECURSION;
|
||||
|
|
Loading…
Reference in a new issue