Skip to content
Snippets Groups Projects
Commit ff61c5d5 authored by Mikhail Svechnikov's avatar Mikhail Svechnikov
Browse files

[m.regenerate_roughness_3d] Manual regeneration of roughness on 3D view ()

Merging branch 'm.regenerate_roughness_3d'  into 'main'.

See merge request !2725
parents adceabef 5fa1b59d
No related branches found
No related tags found
1 merge request!2725Manual regeneration of roughness on 3D view
Pipeline #162189 passed
Showing with 125 additions and 26 deletions
......@@ -35,6 +35,7 @@ const QString Roughness("Roughness");
const QString Layout("Layout");
const QString ExpandLayerGroupbox("ExpandLayerGroupbox");
const QString ExpandRoughnessGroupbox("ExpandRoughnessGroupbox");
const QString RoughnessSeed("RoughnessSeed");
} // namespace Tag
......@@ -120,6 +121,7 @@ void LayerItem::writeTo(QXmlStreamWriter* w) const
XML::writeTaggedElement(w, Tag::Layout, *layout);
XML::writeTaggedValue(w, Tag::ExpandLayerGroupbox, expandLayer);
XML::writeTaggedValue(w, Tag::ExpandRoughnessGroupbox, expandRoughness);
XML::writeTaggedValue(w, Tag::RoughnessSeed, roughnessSeed);
}
void LayerItem::readFrom(QXmlStreamReader* r)
......@@ -143,6 +145,8 @@ void LayerItem::readFrom(QXmlStreamReader* r)
expandLayer = XML::readTaggedBool(r, tag);
else if (tag == Tag::ExpandRoughnessGroupbox)
expandRoughness = XML::readTaggedBool(r, tag);
else if (tag == Tag::RoughnessSeed)
roughnessSeed = XML::readTaggedInt(r, tag);
else
r->skipCurrentElement();
}
......
......@@ -62,6 +62,7 @@ public:
bool expandLayer = false;
bool expandRoughness = true;
int roughnessSeed = 0;
private:
uint m_num_slices = 1;
......
......@@ -18,6 +18,7 @@
#include "GUI/Model/Type/PredefinedColors.h"
#include "GUI/Model/Util/Backup.h"
#include "GUI/Model/Util/UtilXML.h"
#include <random>
namespace {
namespace Tag {
......@@ -79,6 +80,11 @@ void SampleItem::addStandardMaterials()
m_materials.addRefractiveMaterialItem(name, 6e-6, 2e-8);
}
int SampleItem::indexOfLayerItem(const LayerItem* item) const
{
return m_layers.index_of(item);
}
LayerItem* SampleItem::createLayerItemAt(int index)
{
if (index < 0)
......@@ -166,3 +172,23 @@ void SampleItem::updateDefaultLayerColors()
col = (col + 1) % colors.size();
}
}
void SampleItem::updateLayerSeeds()
{
if (m_layers.size() < 2)
return;
unsigned seed =
static_cast<unsigned>(std::chrono::system_clock::now().time_since_epoch().count());
std::mt19937 gen(seed);
std::uniform_int_distribution<int> distr(0, std::numeric_limits<int>::max());
const int i_substrate = m_layers.size() - 1;
m_layers[i_substrate]->roughnessSeed = distr(gen);
for (int i = i_substrate - 1; i >= 0; i--) {
const RoughnessItem* roughness = m_layers[i]->roughnessSelection().certainItem();
const bool hasCrosscorr = roughness->certainCrosscorrModel()
|| dynamic_cast<const LinearGrowthRoughnessItem*>(roughness);
m_layers[i]->roughnessSeed = hasCrosscorr ? m_layers[i + 1]->roughnessSeed : distr(gen);
}
}
......@@ -43,6 +43,8 @@ public:
const std::vector<LayerItem*>& layerItems() const { return m_layers.shared(); }
int indexOfLayerItem(const LayerItem* item) const;
//! Creates and inserts a layer at given index.
//!
//! No properties etc. have been initialized; this has to be done by the caller.
......@@ -60,6 +62,7 @@ public:
const MaterialsSet& materialModel() const { return m_materials; }
void updateDefaultLayerColors();
void updateLayerSeeds();
bool expandInfo = true;
......
......@@ -108,18 +108,15 @@ std::unique_ptr<const double2d_t> layerRoughnessMap(const MultiLayer& sample, in
std::unique_ptr<Img3D::Layer> createLayer(const LayerItem& layerItem, const SampleItem& sampleItem,
const SceneGeometry& sceneGeometry, const F3& origin,
int i_layer)
const double2d_t* topRoughMap,
const double2d_t* bottomRoughMap, bool drawBottom)
{
std::unique_ptr<MultiLayer> sample = GUI::ToCore::itemToSample(sampleItem);
int seed = 1; // TODO accept seed from SampleItem/LayerItem
const int i_interface = i_layer - 1;
double s2 = sceneGeometry.layerSize;
double thickness = ::visualLayerThickness(layerItem, sceneGeometry);
ASSERT(thickness > 0);
auto ztop = static_cast<double>(origin.z());
double zbottom = static_cast<double>(origin.z()) - thickness;
auto topRoughMap = ::layerRoughnessMap(*sample, i_interface, sceneGeometry, seed);
auto bottomRoughMap = ::layerRoughnessMap(*sample, i_interface + 1, sceneGeometry, seed);
// visual mesh will later be scaled, so we divide roughness by thickness factor in advance
auto top = topRoughMap ? ::scaledArray(*topRoughMap, 1. / thickness) : nullptr;
......@@ -127,7 +124,7 @@ std::unique_ptr<Img3D::Layer> createLayer(const LayerItem& layerItem, const Samp
std::unique_ptr<Img3D::Layer> result = std::make_unique<Img3D::Layer>(
Img3D::F3Range(Img3D::F3fromR3({-s2, -s2, ztop}), Img3D::F3fromR3({s2, s2, zbottom})),
top.get(), bottom.get());
top.get(), bottom.get(), drawBottom);
QColor color = layerItem.materialColor();
color.setAlphaF(.3);
......@@ -173,11 +170,21 @@ void RealspaceBuilder::populateSample(Model* model, const SampleItem& sampleItem
{
double total_height(0.0);
const std::vector<LayerItem*>& layers = sampleItem.layerItems();
std::unique_ptr<MultiLayer> sample = GUI::ToCore::itemToSample(sampleItem);
OwningVector<const double2d_t> rough_maps;
rough_maps.push_back(nullptr); // top interface of fronting
for (size_t i = 1; i < layers.size(); i++)
rough_maps.push_back(
::layerRoughnessMap(*sample, i - 1, sceneGeometry, layers[i]->roughnessSeed).release());
rough_maps.push_back(nullptr); // bottom interface of substrate
for (size_t i = 0; i < layers.size(); i++) {
const LayerItem* layer = layers[i];
const bool drawBottom = (i + 1 == layers.size());
populateLayer(model, *layer, sampleItem, sceneGeometry, numParticles,
F3(0, 0, static_cast<float>(-total_height)), i);
F3(0, 0, static_cast<float>(-total_height)), rough_maps[i], rough_maps[i + 1],
drawBottom);
if (i != 0)
total_height += ::visualLayerThickness(*layer, sceneGeometry);
}
......@@ -186,10 +193,33 @@ void RealspaceBuilder::populateSample(Model* model, const SampleItem& sampleItem
void RealspaceBuilder::populateLayer(Model* model, const LayerItem& layerItem,
const SampleItem& sampleItem,
const SceneGeometry& sceneGeometry, unsigned& numParticles,
const F3& origin, int i_layer) const
const F3& origin, const double2d_t* topRoughMap,
const double2d_t* bottomRoughMap, bool drawBottom) const
{
bool isTopLayer = (i_layer == 0);
auto layer = ::createLayer(layerItem, sampleItem, sceneGeometry, origin, i_layer);
const int i_layer = sampleItem.indexOfLayerItem(&layerItem);
const bool isTopLayer = (i_layer == 0);
std::unique_ptr<Img3D::Layer> layer;
// individual layer visualization
if (!topRoughMap && !bottomRoughMap) {
std::unique_ptr<MultiLayer> sample = GUI::ToCore::itemToSample(sampleItem);
const int i_interface = i_layer - 1;
auto new_topRoughMap =
::layerRoughnessMap(*sample, i_interface, sceneGeometry, layerItem.roughnessSeed);
std::unique_ptr<const double2d_t> new_bottomRoughMap;
if (i_layer + 1 < int(sampleItem.layerItems().size())) {
const LayerItem* layerItemBelow = sampleItem.layerItems()[i_layer + 1];
new_bottomRoughMap = ::layerRoughnessMap(*sample, i_interface + 1, sceneGeometry,
layerItemBelow->roughnessSeed);
}
layer = ::createLayer(layerItem, sampleItem, sceneGeometry, origin, new_topRoughMap.get(),
new_bottomRoughMap.get(), drawBottom);
} else {
layer = ::createLayer(layerItem, sampleItem, sceneGeometry, origin, topRoughMap,
bottomRoughMap, drawBottom);
}
if (layer && !isTopLayer)
model->emplaceTransparentBody(layer.release());
......
......@@ -53,7 +53,8 @@ private:
void populateLayer(Img3D::Model* model, const LayerItem& layerItem,
const SampleItem& sampleItem, const SceneGeometry& sceneGeometry,
unsigned int& numParticles, const Img3D::F3& origin = {},
int i_layer = -1) const;
const double2d_t* topRoughMap = nullptr,
const double2d_t* bottomRoughMap = nullptr, bool drawBottom = true) const;
void populateLayout(Img3D::Model* model, const ParticleLayoutItem& layoutItem,
const SceneGeometry& sceneGeometry, unsigned int& numParticles,
......
......@@ -52,6 +52,9 @@ RealspacePanel::RealspacePanel(QWidget* parent)
action = createAction("Reduce", "Decrease layer size");
connect(action, &QAction::triggered, [this] { m_widget->changeLayerSize(0.8); });
action = createAction("Regenerate roughness", "Regenerate random roughness on interfaces");
connect(action, &QAction::triggered, m_widget, &RealspaceWidget::regenerateRoughness);
auto* mainLayout = new QVBoxLayout(this);
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->setSpacing(0);
......
......@@ -156,3 +156,9 @@ void RealspaceWidget::topView()
{
m_canvas->topView();
}
void RealspaceWidget::regenerateRoughness()
{
m_containing_sample->updateLayerSeeds();
updateRealScene();
}
......@@ -40,6 +40,7 @@ public:
void defaultView();
void sideView();
void topView();
void regenerateRoughness();
void changeLayerSize(double layerSizeChangeScale);
void savePicture();
void resetRealScene();
......
......@@ -45,7 +45,8 @@ Geometry::Mesh Geometry::meshBox()
return makeMesh(vs);
}
Geometry::Mesh Geometry::meshRoughBox(const double2d_t* topR, const double2d_t* bottomR)
Geometry::Mesh Geometry::meshRoughBox(const double2d_t* topR, const double2d_t* bottomR,
bool drawBottom)
{
ASSERT(topR || bottomR);
const double2d_t* base = topR ? topR : bottomR;
......@@ -78,7 +79,7 @@ Geometry::Mesh Geometry::meshRoughBox(const double2d_t* topR, const double2d_t*
const F3 v2 = F3(x2, y2, D + t[i + 1][j + 1]);
const F3 v3 = F3(x1, y2, D + t[i][j + 1]);
const F3 v4 = F3(x1, y1, D + t[i][j]);
vs.addQuad(v1, v2, v3, v4);
vs.addQuad(v1, v2, v3, v4); // visible from above
}
}
......@@ -121,9 +122,28 @@ Geometry::Mesh Geometry::meshRoughBox(const double2d_t* topR, const double2d_t*
}
ASSERT(num_vertices == vs.count());
// bottom plane only if there is no underlying layer
if (!bottomR)
vs.addQuad({+D, -D, -D}, {-D, -D, -D}, {-D, +D, -D}, {+D, +D, -D});
if (drawBottom) {
// bottom plane only if there is no underlying layer
if (!bottomR)
vs.addQuad({+D, -D, -D}, {-D, -D, -D}, {-D, +D, -D},
{+D, +D, -D}); // visible from below
else
// bottom surface
for (int j = 0; j < M - 1; j++) {
const float y1 = -D + dy * j;
const float y2 = y1 + dy;
for (int i = 0; i < N - 1; i++) {
const float x1 = -D + dx * i;
const float x2 = x1 + dx;
const F3 v1 = F3(x2, y1, -D + b[i + 1][j]);
const F3 v2 = F3(x2, y2, -D + b[i + 1][j + 1]);
const F3 v3 = F3(x1, y2, -D + b[i][j + 1]);
const F3 v4 = F3(x1, y1, -D + b[i][j]);
vs.addQuad(v1, v2, v3, v4); // visible from above
vs.addQuad(v4, v3, v2, v1); // visible from below
}
}
}
return makeMesh(vs);
}
......
......@@ -55,10 +55,11 @@ void Geometry::Vertices::addFan(const Vertices& vs, const Indices& is)
//------------------------------------------------------------------------------
Geometry::Geometry(GeometricID::Key key_, const double2d_t* top, const double2d_t* bottom)
Geometry::Geometry(GeometricID::Key key_, const double2d_t* top, const double2d_t* bottom,
bool drawBottom)
: m_key(key_)
{
m_mesh = meshRoughBox(top, bottom);
m_mesh = meshRoughBox(top, bottom, drawBottom);
}
Geometry::Geometry(GeometricID::Key key_)
......
......@@ -61,7 +61,7 @@ public:
using Mesh = QVector<VertexAndNormal>;
Geometry(GeometricID::Key);
Geometry(GeometricID::Key, const double2d_t* top, const double2d_t* bottom);
Geometry(GeometricID::Key, const double2d_t* top, const double2d_t* bottom, bool drawBottom);
virtual ~Geometry();
const Mesh& mesh() const { return m_mesh; }
......@@ -76,7 +76,8 @@ private:
static Mesh meshPlane();
static Mesh meshBox();
static Mesh meshRoughBox(const double2d_t*, const double2d_t*);
static Mesh meshRoughBox(const double2d_t* topRough, const double2d_t* bottomRough,
bool drawBottom);
static Mesh meshSphere(float cut, float baseShift = 0.0f, float removedTop = 0.0f);
static Mesh meshColumn(float ratio_Rt_Rb, float numSides);
static Mesh meshIcosahedron();
......
......@@ -17,8 +17,8 @@
namespace Img3D {
Layer::Layer(F3Range d, const double2d_t* top, const double2d_t* bottom)
: PlottableBody(GeometricID::Key(GeometricID::BaseShape::Box), top, bottom)
Layer::Layer(F3Range d, const double2d_t* top, const double2d_t* bottom, bool drawBottom)
: PlottableBody(GeometricID::Key(GeometricID::BaseShape::Box), top, bottom, drawBottom)
{
transform(d.size(), F3(0, 0, 0), d.mid());
}
......
......@@ -24,7 +24,8 @@ class RoughnessItem;
//! Particle layer: a transparent box
class Layer : public PlottableBody {
public:
Layer(F3Range, const double2d_t* top = nullptr, const double2d_t* bottom = nullptr);
Layer(F3Range, const double2d_t* top = nullptr, const double2d_t* bottom = nullptr,
bool drawBottom = false);
};
} // namespace Img3D
......
......@@ -66,13 +66,14 @@ QColor const clrObject = Qt::lightGray;
QColor const clrObject = Qt::black;
#endif
PlottableBody::PlottableBody(GeometricID::Key gky_, const double2d_t* top, const double2d_t* bottom)
PlottableBody::PlottableBody(GeometricID::Key gky_, const double2d_t* top, const double2d_t* bottom,
bool drawBottom)
: isNull(false)
, m_color(clrObject)
, gky(gky_)
{
if (top || bottom)
m_geo = std::shared_ptr<Geometry>(new Geometry(gky, top, bottom));
m_geo = std::make_shared<Geometry>(gky, top, bottom, drawBottom);
}
PlottableBody::~PlottableBody()
......
......@@ -32,7 +32,7 @@ class RoughnessItem;
class PlottableBody {
public:
PlottableBody(GeometricID::Key, const double2d_t* top = nullptr,
const double2d_t* bottom = nullptr);
const double2d_t* bottom = nullptr, bool drawBottom = false);
virtual ~PlottableBody();
const QColor& color() const { return m_color; }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment