mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 08:57:27 +02:00
Sphere tools for voxel editing.
This commit is contained in:
parent
926f0d099c
commit
33faffd9d4
6 changed files with 490 additions and 0 deletions
|
@ -126,6 +126,8 @@ MetavoxelEditor::MetavoxelEditor() :
|
||||||
addTool(new EraseHeightfieldTool(this));
|
addTool(new EraseHeightfieldTool(this));
|
||||||
addTool(new VoxelColorBoxTool(this));
|
addTool(new VoxelColorBoxTool(this));
|
||||||
addTool(new VoxelMaterialBoxTool(this));
|
addTool(new VoxelMaterialBoxTool(this));
|
||||||
|
addTool(new VoxelColorSphereTool(this));
|
||||||
|
addTool(new VoxelMaterialSphereTool(this));
|
||||||
|
|
||||||
updateAttributes();
|
updateAttributes();
|
||||||
|
|
||||||
|
@ -1282,3 +1284,110 @@ void VoxelMaterialBoxTool::updateTexture() {
|
||||||
MaterialObject* material = static_cast<MaterialObject*>(_materialEditor->getObject().data());
|
MaterialObject* material = static_cast<MaterialObject*>(_materialEditor->getObject().data());
|
||||||
_texture = Application::getInstance()->getTextureCache()->getTexture(material->getDiffuse(), SPLAT_TEXTURE);
|
_texture = Application::getInstance()->getTextureCache()->getTexture(material->getDiffuse(), SPLAT_TEXTURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SphereTool::SphereTool(MetavoxelEditor* editor, const QString& name) :
|
||||||
|
MetavoxelTool(editor, name, false, true) {
|
||||||
|
|
||||||
|
QWidget* widget = new QWidget();
|
||||||
|
widget->setLayout(_form = new QFormLayout());
|
||||||
|
layout()->addWidget(widget);
|
||||||
|
|
||||||
|
_form->addRow("Radius:", _radius = new QDoubleSpinBox());
|
||||||
|
_radius->setSingleStep(0.01);
|
||||||
|
_radius->setMaximum(FLT_MAX);
|
||||||
|
_radius->setValue(1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SphereTool::render() {
|
||||||
|
if (Application::getInstance()->isMouseHidden()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
glm::quat rotation = _editor->getGridRotation();
|
||||||
|
glm::quat inverseRotation = glm::inverse(rotation);
|
||||||
|
glm::vec3 rayOrigin = inverseRotation * Application::getInstance()->getMouseRayOrigin();
|
||||||
|
glm::vec3 rayDirection = inverseRotation * Application::getInstance()->getMouseRayDirection();
|
||||||
|
float position = _editor->getGridPosition();
|
||||||
|
if (glm::abs(rayDirection.z) < EPSILON) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
float distance = (position - rayOrigin.z) / rayDirection.z;
|
||||||
|
_position = Application::getInstance()->getMouseRayOrigin() +
|
||||||
|
Application::getInstance()->getMouseRayDirection() * distance;
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(_position.x, _position.y, _position.z);
|
||||||
|
|
||||||
|
const float CURSOR_ALPHA = 0.5f;
|
||||||
|
QColor color = getColor();
|
||||||
|
glColor4f(color.redF(), color.greenF(), color.blueF(), CURSOR_ALPHA);
|
||||||
|
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
|
||||||
|
glutSolidSphere(_radius->value(), 10, 10);
|
||||||
|
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SphereTool::eventFilter(QObject* watched, QEvent* event) {
|
||||||
|
if (event->type() == QEvent::Wheel) {
|
||||||
|
float angle = static_cast<QWheelEvent*>(event)->angleDelta().y();
|
||||||
|
const float ANGLE_SCALE = 1.0f / 1000.0f;
|
||||||
|
_radius->setValue(_radius->value() * glm::pow(2.0f, angle * ANGLE_SCALE));
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else if (event->type() == QEvent::MouseButtonPress) {
|
||||||
|
applyValue(_position, _radius->value());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
VoxelColorSphereTool::VoxelColorSphereTool(MetavoxelEditor* editor) :
|
||||||
|
SphereTool(editor, "Set Voxel Color (Sphere)") {
|
||||||
|
|
||||||
|
_form->addRow("Color:", _color = new QColorEditor(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VoxelColorSphereTool::appliesTo(const AttributePointer& attribute) const {
|
||||||
|
return attribute->inherits("VoxelColorAttribute");
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor VoxelColorSphereTool::getColor() {
|
||||||
|
return _color->getColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelColorSphereTool::applyValue(const glm::vec3& position, float radius) {
|
||||||
|
MetavoxelEditMessage message = { QVariant::fromValue(VoxelColorSphereEdit(position, radius,
|
||||||
|
_editor->getGridSpacing(), _color->getColor())) };
|
||||||
|
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
VoxelMaterialSphereTool::VoxelMaterialSphereTool(MetavoxelEditor* editor) :
|
||||||
|
SphereTool(editor, "Set Voxel Material (Sphere)") {
|
||||||
|
|
||||||
|
_form->addRow(_materialEditor = new SharedObjectEditor(&MaterialObject::staticMetaObject, false));
|
||||||
|
connect(_materialEditor, &SharedObjectEditor::objectChanged, this, &VoxelMaterialSphereTool::updateTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VoxelMaterialSphereTool::appliesTo(const AttributePointer& attribute) const {
|
||||||
|
return attribute->inherits("VoxelColorAttribute");
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor VoxelMaterialSphereTool::getColor() {
|
||||||
|
return _texture ? _texture->getAverageColor() : QColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelMaterialSphereTool::applyValue(const glm::vec3& position, float radius) {
|
||||||
|
SharedObjectPointer material = _materialEditor->getObject();
|
||||||
|
_materialEditor->detachObject();
|
||||||
|
MetavoxelEditMessage message = { QVariant::fromValue(VoxelMaterialSphereEdit(position, radius,
|
||||||
|
_editor->getGridSpacing(), material, _texture ? _texture->getAverageColor() : QColor())) };
|
||||||
|
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelMaterialSphereTool::updateTexture() {
|
||||||
|
MaterialObject* material = static_cast<MaterialObject*>(_materialEditor->getObject().data());
|
||||||
|
_texture = Application::getInstance()->getTextureCache()->getTexture(material->getDiffuse(), SPLAT_TEXTURE);
|
||||||
|
}
|
||||||
|
|
|
@ -455,4 +455,75 @@ private:
|
||||||
QSharedPointer<NetworkTexture> _texture;
|
QSharedPointer<NetworkTexture> _texture;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Base class for tools based on a sphere brush.
|
||||||
|
class SphereTool : public MetavoxelTool {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
SphereTool(MetavoxelEditor* editor, const QString& name);
|
||||||
|
|
||||||
|
virtual void render();
|
||||||
|
|
||||||
|
virtual bool eventFilter(QObject* watched, QEvent* event);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual QColor getColor() = 0;
|
||||||
|
|
||||||
|
virtual void applyValue(const glm::vec3& position, float radius) = 0;
|
||||||
|
|
||||||
|
QFormLayout* _form;
|
||||||
|
QDoubleSpinBox* _radius;
|
||||||
|
|
||||||
|
glm::vec3 _position;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Allows setting voxel colors by moving a sphere around.
|
||||||
|
class VoxelColorSphereTool : public SphereTool {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
VoxelColorSphereTool(MetavoxelEditor* editor);
|
||||||
|
|
||||||
|
virtual bool appliesTo(const AttributePointer& attribute) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual QColor getColor();
|
||||||
|
|
||||||
|
virtual void applyValue(const glm::vec3& position, float radius);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
QColorEditor* _color;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Allows setting voxel materials by moving a sphere around.
|
||||||
|
class VoxelMaterialSphereTool : public SphereTool {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
VoxelMaterialSphereTool(MetavoxelEditor* editor);
|
||||||
|
|
||||||
|
virtual bool appliesTo(const AttributePointer& attribute) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual QColor getColor();
|
||||||
|
|
||||||
|
virtual void applyValue(const glm::vec3& position, float radius);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void updateTexture();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
SharedObjectEditor* _materialEditor;
|
||||||
|
QSharedPointer<NetworkTexture> _texture;
|
||||||
|
};
|
||||||
|
|
||||||
#endif // hifi_MetavoxelEditor_h
|
#endif // hifi_MetavoxelEditor_h
|
||||||
|
|
|
@ -406,6 +406,10 @@ QRgb packNormal(const glm::vec3& normal) {
|
||||||
return qRgb((char)(normal.x * CHAR_SCALE), (char)(normal.y * CHAR_SCALE), (char)(normal.z * CHAR_SCALE));
|
return qRgb((char)(normal.x * CHAR_SCALE), (char)(normal.y * CHAR_SCALE), (char)(normal.z * CHAR_SCALE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRgb packNormal(const glm::vec3& normal, int alpha) {
|
||||||
|
return qRgba((char)(normal.x * CHAR_SCALE), (char)(normal.y * CHAR_SCALE), (char)(normal.z * CHAR_SCALE), alpha);
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec3 unpackNormal(QRgb value) {
|
glm::vec3 unpackNormal(QRgb value) {
|
||||||
return glm::vec3((char)qRed(value) * INVERSE_CHAR_SCALE, (char)qGreen(value) * INVERSE_CHAR_SCALE,
|
return glm::vec3((char)qRed(value) * INVERSE_CHAR_SCALE, (char)qGreen(value) * INVERSE_CHAR_SCALE,
|
||||||
(char)qBlue(value) * INVERSE_CHAR_SCALE);
|
(char)qBlue(value) * INVERSE_CHAR_SCALE);
|
||||||
|
|
|
@ -416,6 +416,9 @@ public:
|
||||||
/// Packs a normal into an RGB value.
|
/// Packs a normal into an RGB value.
|
||||||
QRgb packNormal(const glm::vec3& normal);
|
QRgb packNormal(const glm::vec3& normal);
|
||||||
|
|
||||||
|
/// Packs a normal (plus extra alpha value) into an RGBA value.
|
||||||
|
QRgb packNormal(const glm::vec3& normal, int alpha);
|
||||||
|
|
||||||
/// Unpacks a normal from an RGB value.
|
/// Unpacks a normal from an RGB value.
|
||||||
glm::vec3 unpackNormal(QRgb value);
|
glm::vec3 unpackNormal(QRgb value);
|
||||||
|
|
||||||
|
|
|
@ -814,3 +814,267 @@ void VoxelMaterialBoxEdit::apply(MetavoxelData& data, const WeakSharedObjectHash
|
||||||
VoxelMaterialBoxEditVisitor visitor(region, granularity, material, averageColor);
|
VoxelMaterialBoxEditVisitor visitor(region, granularity, material, averageColor);
|
||||||
data.guide(visitor);
|
data.guide(visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VoxelColorSphereEdit::VoxelColorSphereEdit(const glm::vec3& center, float radius, float granularity, const QColor& color) :
|
||||||
|
center(center),
|
||||||
|
radius(radius),
|
||||||
|
granularity(granularity),
|
||||||
|
color(color) {
|
||||||
|
}
|
||||||
|
|
||||||
|
class VoxelMaterialSphereEditVisitor : public MetavoxelVisitor {
|
||||||
|
public:
|
||||||
|
|
||||||
|
VoxelMaterialSphereEditVisitor(const glm::vec3& center, float radius, const Box& bounds, float granularity,
|
||||||
|
const SharedObjectPointer& material, const QColor& color);
|
||||||
|
|
||||||
|
virtual int visit(MetavoxelInfo& info);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
glm::vec3 _center;
|
||||||
|
float _radius;
|
||||||
|
Box _bounds;
|
||||||
|
float _granularity;
|
||||||
|
SharedObjectPointer _material;
|
||||||
|
QColor _color;
|
||||||
|
float _blockSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
VoxelMaterialSphereEditVisitor::VoxelMaterialSphereEditVisitor(const glm::vec3& center, float radius, const Box& bounds,
|
||||||
|
float granularity, const SharedObjectPointer& material, const QColor& color) :
|
||||||
|
MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getVoxelColorAttribute() <<
|
||||||
|
AttributeRegistry::getInstance()->getVoxelHermiteAttribute() <<
|
||||||
|
AttributeRegistry::getInstance()->getVoxelMaterialAttribute(), QVector<AttributePointer>() <<
|
||||||
|
AttributeRegistry::getInstance()->getVoxelColorAttribute() <<
|
||||||
|
AttributeRegistry::getInstance()->getVoxelHermiteAttribute() <<
|
||||||
|
AttributeRegistry::getInstance()->getVoxelMaterialAttribute()),
|
||||||
|
_center(center),
|
||||||
|
_radius(radius),
|
||||||
|
_bounds(bounds),
|
||||||
|
_granularity(granularity),
|
||||||
|
_material(material),
|
||||||
|
_color(color),
|
||||||
|
_blockSize(granularity * VOXEL_BLOCK_SIZE) {
|
||||||
|
}
|
||||||
|
|
||||||
|
int VoxelMaterialSphereEditVisitor::visit(MetavoxelInfo& info) {
|
||||||
|
Box bounds = info.getBounds();
|
||||||
|
if (!bounds.intersects(_bounds)) {
|
||||||
|
return STOP_RECURSION;
|
||||||
|
}
|
||||||
|
if (info.size > _blockSize) {
|
||||||
|
return DEFAULT_ORDER;
|
||||||
|
}
|
||||||
|
VoxelColorDataPointer colorPointer = info.inputValues.at(0).getInlineValue<VoxelColorDataPointer>();
|
||||||
|
QVector<QRgb> colorContents = (colorPointer && colorPointer->getSize() == VOXEL_BLOCK_SAMPLES) ?
|
||||||
|
colorPointer->getContents() : QVector<QRgb>(VOXEL_BLOCK_VOLUME);
|
||||||
|
|
||||||
|
Box overlap = info.getBounds().getIntersection(_bounds);
|
||||||
|
float scale = VOXEL_BLOCK_SIZE / info.size;
|
||||||
|
overlap.minimum = (overlap.minimum - info.minimum) * scale;
|
||||||
|
overlap.maximum = (overlap.maximum - info.minimum) * scale;
|
||||||
|
int minX = glm::ceil(overlap.minimum.x);
|
||||||
|
int minY = glm::ceil(overlap.minimum.y);
|
||||||
|
int minZ = glm::ceil(overlap.minimum.z);
|
||||||
|
int sizeX = (int)overlap.maximum.x - minX + 1;
|
||||||
|
int sizeY = (int)overlap.maximum.y - minY + 1;
|
||||||
|
int sizeZ = (int)overlap.maximum.z - minZ + 1;
|
||||||
|
|
||||||
|
glm::vec3 relativeCenter = (_center - info.minimum) * scale;
|
||||||
|
float relativeRadius = _radius * scale;
|
||||||
|
float relativeRadiusSquared = relativeRadius * relativeRadius;
|
||||||
|
|
||||||
|
QRgb rgb = _color.rgba();
|
||||||
|
glm::vec3 position(0.0f, 0.0f, minZ);
|
||||||
|
for (QRgb* destZ = colorContents.data() + minZ * VOXEL_BLOCK_AREA + minY * VOXEL_BLOCK_SAMPLES + minX,
|
||||||
|
*endZ = destZ + sizeZ * VOXEL_BLOCK_AREA; destZ != endZ; destZ += VOXEL_BLOCK_AREA, position.z++) {
|
||||||
|
position.y = minY;
|
||||||
|
for (QRgb* destY = destZ, *endY = destY + sizeY * VOXEL_BLOCK_SAMPLES; destY != endY;
|
||||||
|
destY += VOXEL_BLOCK_SAMPLES, position.y++) {
|
||||||
|
position.x = minX;
|
||||||
|
for (QRgb* destX = destY, *endX = destX + sizeX; destX != endX; destX++, position.x++) {
|
||||||
|
if (glm::distance(relativeCenter, position) <= relativeRadius) {
|
||||||
|
*destX = rgb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VoxelColorDataPointer newColorPointer(new VoxelColorData(colorContents, VOXEL_BLOCK_SAMPLES));
|
||||||
|
info.outputValues[0] = AttributeValue(info.inputValues.at(0).getAttribute(),
|
||||||
|
encodeInline<VoxelColorDataPointer>(newColorPointer));
|
||||||
|
|
||||||
|
VoxelHermiteDataPointer hermitePointer = info.inputValues.at(1).getInlineValue<VoxelHermiteDataPointer>();
|
||||||
|
QVector<QRgb> hermiteContents = (hermitePointer && hermitePointer->getSize() == VOXEL_BLOCK_SAMPLES) ?
|
||||||
|
hermitePointer->getContents() : QVector<QRgb>(VOXEL_BLOCK_VOLUME * VoxelHermiteData::EDGE_COUNT);
|
||||||
|
int hermiteArea = VOXEL_BLOCK_AREA * VoxelHermiteData::EDGE_COUNT;
|
||||||
|
int hermiteSamples = VOXEL_BLOCK_SAMPLES * VoxelHermiteData::EDGE_COUNT;
|
||||||
|
|
||||||
|
int hermiteMinX = minX, hermiteMinY = minY, hermiteMinZ = minZ;
|
||||||
|
int hermiteSizeX = sizeX, hermiteSizeY = sizeY, hermiteSizeZ = sizeZ;
|
||||||
|
if (minX > 0) {
|
||||||
|
hermiteMinX--;
|
||||||
|
hermiteSizeX++;
|
||||||
|
}
|
||||||
|
if (minY > 0) {
|
||||||
|
hermiteMinY--;
|
||||||
|
hermiteSizeY++;
|
||||||
|
}
|
||||||
|
if (minZ > 0) {
|
||||||
|
hermiteMinZ--;
|
||||||
|
hermiteSizeZ++;
|
||||||
|
}
|
||||||
|
QRgb* hermiteDestZ = hermiteContents.data() + hermiteMinZ * hermiteArea + hermiteMinY * hermiteSamples +
|
||||||
|
hermiteMinX * VoxelHermiteData::EDGE_COUNT;
|
||||||
|
for (int z = hermiteMinZ, hermiteMaxZ = z + hermiteSizeZ - 1; z <= hermiteMaxZ; z++, hermiteDestZ += hermiteArea) {
|
||||||
|
QRgb* hermiteDestY = hermiteDestZ;
|
||||||
|
for (int y = hermiteMinY, hermiteMaxY = y + hermiteSizeY - 1; y <= hermiteMaxY; y++, hermiteDestY += hermiteSamples) {
|
||||||
|
QRgb* hermiteDestX = hermiteDestY;
|
||||||
|
for (int x = hermiteMinX, hermiteMaxX = x + hermiteSizeX - 1; x <= hermiteMaxX; x++,
|
||||||
|
hermiteDestX += VoxelHermiteData::EDGE_COUNT) {
|
||||||
|
hermiteDestX[0] = 0x0;
|
||||||
|
glm::vec3 offset(x - relativeCenter.x, y - relativeCenter.y, z - relativeCenter.z);
|
||||||
|
if (x != VOXEL_BLOCK_SIZE) {
|
||||||
|
const QRgb* color = colorContents.constData() + z * VOXEL_BLOCK_AREA + y * VOXEL_BLOCK_SAMPLES + x;
|
||||||
|
int alpha0 = qAlpha(color[0]);
|
||||||
|
if (alpha0 != qAlpha(color[1])) {
|
||||||
|
float radicand = relativeRadiusSquared - offset.y * offset.y - offset.z * offset.z;
|
||||||
|
float parameter = 0.5f;
|
||||||
|
if (radicand >= 0.0f) {
|
||||||
|
float root = glm::sqrt(radicand);
|
||||||
|
parameter = -offset.x - root;
|
||||||
|
if (parameter < 0.0f || parameter > 1.0f) {
|
||||||
|
parameter = glm::clamp(-offset.x + root, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glm::vec3 normal = offset + glm::vec3(parameter, 0.0f, 0.0f);
|
||||||
|
float length = glm::length(normal);
|
||||||
|
if (length > EPSILON) {
|
||||||
|
normal /= length;
|
||||||
|
} else {
|
||||||
|
normal = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||||
|
}
|
||||||
|
hermiteDestX[0] = packNormal(normal, parameter * EIGHT_BIT_MAXIMUM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hermiteDestX[1] = 0x0;
|
||||||
|
if (y != VOXEL_BLOCK_SIZE) {
|
||||||
|
const QRgb* color = colorContents.constData() + z * VOXEL_BLOCK_AREA + y * VOXEL_BLOCK_SAMPLES + x;
|
||||||
|
int alpha0 = qAlpha(color[0]);
|
||||||
|
if (alpha0 != qAlpha(color[VOXEL_BLOCK_SAMPLES])) {
|
||||||
|
float radicand = relativeRadiusSquared - offset.x * offset.x - offset.z * offset.z;
|
||||||
|
float parameter = 0.5f;
|
||||||
|
if (radicand >= 0.0f) {
|
||||||
|
float root = glm::sqrt(radicand);
|
||||||
|
parameter = -offset.y - root;
|
||||||
|
if (parameter < 0.0f || parameter > 1.0f) {
|
||||||
|
parameter = glm::clamp(-offset.y + root, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glm::vec3 normal = offset + glm::vec3(parameter, 0.0f, 0.0f);
|
||||||
|
float length = glm::length(normal);
|
||||||
|
if (length > EPSILON) {
|
||||||
|
normal /= length;
|
||||||
|
} else {
|
||||||
|
normal = glm::vec3(1.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
hermiteDestX[1] = packNormal(normal, parameter * EIGHT_BIT_MAXIMUM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hermiteDestX[2] = 0x0;
|
||||||
|
if (z != VOXEL_BLOCK_SIZE) {
|
||||||
|
const QRgb* color = colorContents.constData() + z * VOXEL_BLOCK_AREA + y * VOXEL_BLOCK_SAMPLES + x;
|
||||||
|
int alpha0 = qAlpha(color[0]);
|
||||||
|
if (alpha0 != qAlpha(color[VOXEL_BLOCK_AREA])) {
|
||||||
|
float radicand = relativeRadiusSquared - offset.x * offset.x - offset.y * offset.y;
|
||||||
|
float parameter = 0.5f;
|
||||||
|
if (radicand >= 0.0f) {
|
||||||
|
float root = glm::sqrt(radicand);
|
||||||
|
parameter = -offset.z - root;
|
||||||
|
if (parameter < 0.0f || parameter > 1.0f) {
|
||||||
|
parameter = glm::clamp(-offset.z + root, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glm::vec3 normal = offset + glm::vec3(parameter, 0.0f, 0.0f);
|
||||||
|
float length = glm::length(normal);
|
||||||
|
if (length > EPSILON) {
|
||||||
|
normal /= length;
|
||||||
|
} else {
|
||||||
|
normal = glm::vec3(1.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
hermiteDestX[2] = packNormal(normal, parameter * EIGHT_BIT_MAXIMUM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VoxelHermiteDataPointer newHermitePointer(new VoxelHermiteData(hermiteContents, VOXEL_BLOCK_SAMPLES));
|
||||||
|
info.outputValues[1] = AttributeValue(info.inputValues.at(1).getAttribute(),
|
||||||
|
encodeInline<VoxelHermiteDataPointer>(newHermitePointer));
|
||||||
|
|
||||||
|
VoxelMaterialDataPointer materialPointer = info.inputValues.at(2).getInlineValue<VoxelMaterialDataPointer>();
|
||||||
|
QByteArray materialContents;
|
||||||
|
QVector<SharedObjectPointer> materials;
|
||||||
|
if (materialPointer && materialPointer->getSize() == VOXEL_BLOCK_SAMPLES) {
|
||||||
|
materialContents = materialPointer->getContents();
|
||||||
|
materials = materialPointer->getMaterials();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
materialContents = QByteArray(VOXEL_BLOCK_VOLUME, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uchar materialIndex = getMaterialIndex(_material, materials, materialContents);
|
||||||
|
position.z = minZ;
|
||||||
|
for (uchar* destZ = (uchar*)materialContents.data() + minZ * VOXEL_BLOCK_AREA + minY * VOXEL_BLOCK_SAMPLES + minX,
|
||||||
|
*endZ = destZ + sizeZ * VOXEL_BLOCK_AREA; destZ != endZ; destZ += VOXEL_BLOCK_AREA, position.z++) {
|
||||||
|
position.y = minY;
|
||||||
|
for (uchar* destY = destZ, *endY = destY + sizeY * VOXEL_BLOCK_SAMPLES; destY != endY;
|
||||||
|
destY += VOXEL_BLOCK_SAMPLES, position.y++) {
|
||||||
|
position.x = minX;
|
||||||
|
for (uchar* destX = destY, *endX = destX + sizeX; destX != endX; destX++, position.x++) {
|
||||||
|
if (glm::distance(relativeCenter, position) <= relativeRadius) {
|
||||||
|
*destX = materialIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clearUnusedMaterials(materials, materialContents);
|
||||||
|
VoxelMaterialDataPointer newMaterialPointer(new VoxelMaterialData(materialContents, VOXEL_BLOCK_SAMPLES, materials));
|
||||||
|
info.outputValues[2] = AttributeValue(_inputs.at(2), encodeInline<VoxelMaterialDataPointer>(newMaterialPointer));
|
||||||
|
|
||||||
|
return STOP_RECURSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelColorSphereEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
||||||
|
// expand to fit the entire edit
|
||||||
|
glm::vec3 extents(radius, radius, radius);
|
||||||
|
Box bounds(center - extents, center + extents);
|
||||||
|
while (!data.getBounds().contains(bounds)) {
|
||||||
|
data.expand();
|
||||||
|
}
|
||||||
|
VoxelMaterialSphereEditVisitor visitor(center, radius, bounds, granularity, SharedObjectPointer(), color);
|
||||||
|
data.guide(visitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
VoxelMaterialSphereEdit::VoxelMaterialSphereEdit(const glm::vec3& center, float radius, float granularity,
|
||||||
|
const SharedObjectPointer& material, const QColor& averageColor) :
|
||||||
|
center(center),
|
||||||
|
radius(radius),
|
||||||
|
granularity(granularity),
|
||||||
|
material(material),
|
||||||
|
averageColor(averageColor) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelMaterialSphereEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
||||||
|
// expand to fit the entire edit
|
||||||
|
glm::vec3 extents(radius, radius, radius);
|
||||||
|
Box bounds(center - extents, center + extents);
|
||||||
|
while (!data.getBounds().contains(bounds)) {
|
||||||
|
data.expand();
|
||||||
|
}
|
||||||
|
VoxelMaterialSphereEditVisitor visitor(center, radius, bounds, granularity, material, averageColor);
|
||||||
|
data.guide(visitor);
|
||||||
|
}
|
||||||
|
|
|
@ -296,4 +296,43 @@ public:
|
||||||
|
|
||||||
DECLARE_STREAMABLE_METATYPE(VoxelMaterialBoxEdit)
|
DECLARE_STREAMABLE_METATYPE(VoxelMaterialBoxEdit)
|
||||||
|
|
||||||
|
/// An edit that sets the color of voxels within a sphere to a value.
|
||||||
|
class VoxelColorSphereEdit : public MetavoxelEdit {
|
||||||
|
STREAMABLE
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
STREAM glm::vec3 center;
|
||||||
|
STREAM float radius;
|
||||||
|
STREAM float granularity;
|
||||||
|
STREAM QColor color;
|
||||||
|
|
||||||
|
VoxelColorSphereEdit(const glm::vec3& center = glm::vec3(), float radius = 0.0f,
|
||||||
|
float granularity = 0.0f, const QColor& color = QColor());
|
||||||
|
|
||||||
|
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
DECLARE_STREAMABLE_METATYPE(VoxelColorSphereEdit)
|
||||||
|
|
||||||
|
/// An edit that sets the materials of voxels within a sphere to a value.
|
||||||
|
class VoxelMaterialSphereEdit : public MetavoxelEdit {
|
||||||
|
STREAMABLE
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
STREAM glm::vec3 center;
|
||||||
|
STREAM float radius;
|
||||||
|
STREAM float granularity;
|
||||||
|
STREAM SharedObjectPointer material;
|
||||||
|
STREAM QColor averageColor;
|
||||||
|
|
||||||
|
VoxelMaterialSphereEdit(const glm::vec3& center = glm::vec3(), float radius = 0.0f, float granularity = 0.0f,
|
||||||
|
const SharedObjectPointer& material = SharedObjectPointer(), const QColor& averageColor = QColor());
|
||||||
|
|
||||||
|
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
DECLARE_STREAMABLE_METATYPE(VoxelMaterialSphereEdit)
|
||||||
|
|
||||||
#endif // hifi_MetavoxelMessages_h
|
#endif // hifi_MetavoxelMessages_h
|
||||||
|
|
Loading…
Reference in a new issue