From e08a0144c27a12154be6c0204ba92de7d85fa72b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 6 Nov 2014 19:15:43 -0800 Subject: [PATCH] Cleanup on aisle three! Removed the color/normal/voxelized spanner bits, as well as the throbbing/scripted guides and the notion of spanner masking. --- .../resources/shaders/metavoxel_point.vert | 31 -- interface/src/MetavoxelSystem.cpp | 234 +---------- interface/src/MetavoxelSystem.h | 72 +--- interface/src/ui/MetavoxelEditor.cpp | 243 +----------- interface/src/ui/MetavoxelEditor.h | 15 - .../metavoxels/src/AttributeRegistry.cpp | 220 +---------- libraries/metavoxels/src/AttributeRegistry.h | 100 +---- .../metavoxels/src/MetavoxelClientManager.cpp | 13 - .../metavoxels/src/MetavoxelClientManager.h | 4 - libraries/metavoxels/src/MetavoxelData.cpp | 363 ++---------------- libraries/metavoxels/src/MetavoxelData.h | 115 +----- .../metavoxels/src/MetavoxelMessages.cpp | 180 +-------- libraries/metavoxels/src/MetavoxelMessages.h | 15 - tests/metavoxels/src/MetavoxelTests.cpp | 17 +- 14 files changed, 75 insertions(+), 1547 deletions(-) delete mode 100644 interface/resources/shaders/metavoxel_point.vert diff --git a/interface/resources/shaders/metavoxel_point.vert b/interface/resources/shaders/metavoxel_point.vert deleted file mode 100644 index 02de2bfa01..0000000000 --- a/interface/resources/shaders/metavoxel_point.vert +++ /dev/null @@ -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); -} diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 4c0acc553a..a671452143 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -37,8 +37,6 @@ REGISTER_META_OBJECT(SphereRenderer) REGISTER_META_OBJECT(CuboidRenderer) REGISTER_META_OBJECT(StaticModelRenderer) -static int bufferPointVectorMetaTypeId = qRegisterMetaType(); - 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() << AttributeRegistry::getInstance()->getColorAttribute() << - AttributeRegistry::getInstance()->getNormalAttribute(), QVector() << - 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(); - quint8 alpha = qAlpha(color); - if (alpha > ALPHA_RENDER_THRESHOLD) { - QRgb normal = info.inputValues.at(1).getInlineValue(); - 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() << AttributeRegistry::getInstance()->getSpannersAttribute(), - QVector(), QVector(), QVector(), lod), + QVector(), QVector(), 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() << AttributeRegistry::getInstance()->getSpannersAttribute(), - QVector(), QVector(), QVector(), - lod, encodeOrder(Application::getInstance()->getDisplayViewFrustum()->getDirection())), + QVector(), QVector(), 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(_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(_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(_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; diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index 7e9f2ce2ca..e0fce70c2d 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -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 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 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: diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index e5a1f7f7a4..2b3b0a3870 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -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 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); - - virtual void run(); - -private: - - void voxelize(const glm::vec3& center); - - float _size; - Box _bounds; - float _granularity; - QVector _directionImages; -}; - -Voxelizer::Voxelizer(float size, const Box& bounds, float granularity, const QVector& 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, const glm::vec3& center, float granularity); - - virtual int visit(MetavoxelInfo& info); - -private: - - QVector _directionImages; - glm::vec3 _center; - float _granularity; -}; - -VoxelizationVisitor::VoxelizationVisitor(const QVector& directionImages, - const glm::vec3& center, float granularity) : - MetavoxelVisitor(QVector(), QVector() << - 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(color)); - return STOP_RECURSION; - } - if (distance < closestDistance) { - closestColor = color; - closestDistance = distance; - } - } - info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(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.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; - - 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(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) { diff --git a/interface/src/ui/MetavoxelEditor.h b/interface/src/ui/MetavoxelEditor.h index d17834ae18..5607439807 100644 --- a/interface/src/ui/MetavoxelEditor.h +++ b/interface/src/ui/MetavoxelEditor.h @@ -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 diff --git a/libraries/metavoxels/src/AttributeRegistry.cpp b/libraries/metavoxels/src/AttributeRegistry.cpp index c06e376a25..0ed20386c6 100644 --- a/libraries/metavoxels/src/AttributeRegistry.cpp +++ b/libraries/metavoxels/src/AttributeRegistry.cpp @@ -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(name, defaultValue) { -} - -QRgbAttribute::QRgbAttribute(const QString& name, QRgb defaultValue) : - InlineAttribute(name, defaultValue) { -} - -bool QRgbAttribute::merge(void*& parent, void* children[], bool postRead) const { - QRgb firstValue = decodeInline(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(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(first); - QRgb secondValue = decodeInline(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(source); - QRgb destValue = decodeInline(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().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(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(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(first)); - glm::vec3 secondNormal = unpackNormal(decodeInline(second)); - return encodeInline(packNormal(glm::normalize(glm::mix(firstNormal, secondNormal, alpha)))); -} - -void* PackedNormalAttribute::blend(void* source, void* dest) const { - QRgb sourceValue = decodeInline(source); - QRgb destValue = decodeInline(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(children[i])) != 0) { - return false; - } - } - return true; - } - QRgb parentValue = decodeInline(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(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(children[i])) != 0) { - return false; - } - } - return true; - } - QRgb parentValue = decodeInline(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(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 countIndices(const QByteArray& contents) { return counts; } +const float EIGHT_BIT_MAXIMUM = 255.0f; + uchar getMaterialIndex(const SharedObjectPointer& material, QVector& materials, QByteArray& contents) { if (!(material && static_cast(material.data())->getDiffuse().isValid())) { return 0; diff --git a/libraries/metavoxels/src/AttributeRegistry.h b/libraries/metavoxels/src/AttributeRegistry.h index 945c4df94b..8df23bfae5 100644 --- a/libraries/metavoxels/src/AttributeRegistry.h +++ b/libraries/metavoxels/src/AttributeRegistry.h @@ -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 inline bool SimpleInlineAttribute::merge( return allChildrenEqual; } -/// Simple float attribute. +/// A simple float attribute. class FloatAttribute : public SimpleInlineAttribute { 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 { - 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 DataBlockPointer; /// Base class for blocks of data. diff --git a/libraries/metavoxels/src/MetavoxelClientManager.cpp b/libraries/metavoxels/src/MetavoxelClientManager.cpp index f1c086da67..353e6e8f35 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.cpp +++ b/libraries/metavoxels/src/MetavoxelClientManager.cpp @@ -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); diff --git a/libraries/metavoxels/src/MetavoxelClientManager.h b/libraries/metavoxels/src/MetavoxelClientManager.h index adab59e0ff..bdf56400b0 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.h +++ b/libraries/metavoxels/src/MetavoxelClientManager.h @@ -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); diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index b79903ba8a..4dcc4bd239 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -11,7 +11,6 @@ #include #include -#include #include #include @@ -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() << attribute, - QVector(), QVector(), QVector(), lod), + QVector(), QVector(), 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& spannerInputs, const QVector& spannerMasks, - const QVector& inputs, const QVector& outputs, - const MetavoxelLOD& lod, int order) : - MetavoxelVisitor(inputs + spannerInputs + spannerMasks, outputs, lod), +SpannerVisitor::SpannerVisitor(const QVector& spannerInputs, const QVector& inputs, + const QVector& 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()) { Spanner* spanner = static_cast(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(); - if (maskValue < 0.5f) { - const MetavoxelInfo* nextInfo = &info; - do { - foreach (const SharedObjectPointer& object, nextInfo->inputValues.at( - i - _spannerInputCount).getInlineValue()) { - Spanner* spanner = static_cast(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& spannerInputs, const QVector& spannerMasks, - const QVector& inputs, const QVector& outputs, const MetavoxelLOD& lod) : - RayIntersectionVisitor(origin, direction, inputs + spannerInputs + spannerMasks, outputs, lod), - _spannerInputCount(spannerInputs.size()), - _spannerMaskCount(spannerMasks.size()) { + const QVector& spannerInputs, const QVector& inputs, + const QVector& 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 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()) { Spanner* spanner = static_cast(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(); - if (maskValue < 0.5f) { - const MetavoxelInfo* nextInfo = &info; - do { - foreach (const SharedObjectPointer& object, nextInfo->inputValues.at( - i - _spannerInputCount).getInlineValue()) { - Spanner* spanner = static_cast(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(); - double seconds = QDateTime::currentMSecsSinceEpoch() / 1000.0; - double amplitude = sin(_rate * seconds) * 0.5 + 0.5; - attributeValue.setInlineValue(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& 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(context->callee().data().toVariant().value()); - return getAttributes(engine, guide, guide->_visitation->visitor->getInputs()); -} - -QScriptValue ScriptedMetavoxelGuide::getOutputs(QScriptContext* context, QScriptEngine* engine) { - ScriptedMetavoxelGuide* guide = static_cast(context->callee().data().toVariant().value()); - return getAttributes(engine, guide, guide->_visitation->visitor->getOutputs()); -} - -QScriptValue ScriptedMetavoxelGuide::visit(QScriptContext* context, QScriptEngine* engine) { - ScriptedMetavoxelGuide* guide = static_cast(context->callee().data().toVariant().value()); - - // 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& 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(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& Spanner::getAttributes() const { - static QVector emptyVector; - return emptyVector; -} - -const QVector& Spanner::getVoxelizedAttributes() const { - static QVector 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& Sphere::getAttributes() const { - static QVector attributes = QVector() << - AttributeRegistry::getInstance()->getColorAttribute() << AttributeRegistry::getInstance()->getNormalAttribute(); - return attributes; -} - -const QVector& Sphere::getVoxelizedAttributes() const { - static QVector attributes = QVector() << - 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(_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(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(_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()); - 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(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(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 { diff --git a/libraries/metavoxels/src/MetavoxelData.h b/libraries/metavoxels/src/MetavoxelData.h index 3efb0fc8f2..5dc1a8e7c2 100644 --- a/libraries/metavoxels/src/MetavoxelData.h +++ b/libraries/metavoxels/src/MetavoxelData.h @@ -12,13 +12,10 @@ #ifndef hifi_MetavoxelData_h #define hifi_MetavoxelData_h -#include #include #include #include #include -#include -#include #include #include @@ -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& spannerInputs, - const QVector& spannerMasks = QVector(), const QVector& inputs = QVector(), const QVector& outputs = QVector(), 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& spannerInputs, - const QVector& spannerMasks = QVector(), const QVector& inputs = QVector(), const QVector& outputs = QVector(), 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 _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& getAttributes() const; - - /// Returns a reference to the list of corresponding attributes that we voxelize the spanner into. - virtual const QVector& 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 _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& getAttributes() const; - virtual const QVector& 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: diff --git a/libraries/metavoxels/src/MetavoxelMessages.cpp b/libraries/metavoxels/src/MetavoxelMessages.cpp index c9c2d32b7e..64e7863dee 100644 --- a/libraries/metavoxels/src/MetavoxelMessages.cpp +++ b/libraries/metavoxels/src/MetavoxelMessages.cpp @@ -39,8 +39,7 @@ private: }; BoxSetEditVisitor::BoxSetEditVisitor(const BoxSetEdit& edit) : - MetavoxelVisitor(QVector(), QVector() << edit.value.getAttribute() << - AttributeRegistry::getInstance()->getSpannerMaskAttribute()), + MetavoxelVisitor(QVector(), QVector() << 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(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(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& getUnmaskedSpanners() const { return _unmaskedSpanners; } - - virtual bool visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize); - -private: - - Box _bounds; - QList _unmaskedSpanners; -}; - -GatherUnmaskedSpannersVisitor::GatherUnmaskedSpannersVisitor(const Box& bounds) : - SpannerVisitor(QVector() << 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(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& attributes, Spanner* spanner); - - virtual int visit(MetavoxelInfo& info); - -private: - - Spanner* _spanner; - float _voxelizationSize; - int _steps; -}; - -UpdateSpannerVisitor::UpdateSpannerVisitor(const QVector& attributes, Spanner* spanner) : - MetavoxelVisitor(QVector() << 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()) { - static_cast(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(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(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& getAttributes() const { return _attributes; } - - virtual bool visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize); - -protected: - - QSet _attributes; -}; - -GatherSpannerAttributesVisitor::GatherSpannerAttributesVisitor(const AttributePointer& attribute) : - SpannerVisitor(QVector() << 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& attributes, Spanner* spanner); - - virtual int visit(MetavoxelInfo& info); - -private: - - Spanner* _spanner; -}; - -SetSpannerEditVisitor::SetSpannerEditVisitor(const QVector& attributes, Spanner* spanner) : - MetavoxelVisitor(attributes, QVector() << 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(1.0f)); - } - return STOP_RECURSION; -} - -void SetSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { - Spanner* spanner = static_cast(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) : diff --git a/libraries/metavoxels/src/MetavoxelMessages.h b/libraries/metavoxels/src/MetavoxelMessages.h index 06f2fc9b8d..10477e0486 100644 --- a/libraries/metavoxels/src/MetavoxelMessages.h +++ b/libraries/metavoxels/src/MetavoxelMessages.h @@ -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 diff --git a/tests/metavoxels/src/MetavoxelTests.cpp b/tests/metavoxels/src/MetavoxelTests.cpp index 92f8d0568c..5a6355483d 100644 --- a/tests/metavoxels/src/MetavoxelTests.cpp +++ b/tests/metavoxels/src/MetavoxelTests.cpp @@ -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(), - QVector() << AttributeRegistry::getInstance()->getColorAttribute()), + MetavoxelVisitor(QVector(), QVector() << 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(randomColorValue(), - randomColorValue(), randomColorValue()))); + info.outputValues[0] = OwnedAttributeValue(_outputs.at(0), encodeInline(randFloat())); leafCount++; return STOP_RECURSION; } @@ -812,8 +815,7 @@ private: }; MutateVisitor::MutateVisitor() : - MetavoxelVisitor(QVector(), - QVector() << AttributeRegistry::getInstance()->getColorAttribute()), + MetavoxelVisitor(QVector(), QVector() << 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(randomColorValue(), - randomColorValue(), randomColorValue()))); + info.outputValues[0] = OwnedAttributeValue(_outputs.at(0), encodeInline(randFloat())); _mutationsRemaining--; metavoxelMutationsPerformed++; return STOP_RECURSION;