Add part countershading setting

Countershaded parts will be belly white colored.
master
Jeremy Hu 2019-11-07 21:38:47 +09:30
parent d5d46b8337
commit 5c34ae61ce
19 changed files with 204 additions and 32 deletions

View File

@ -606,16 +606,16 @@ Tips:
<translation>线</translation> <translation>线</translation>
</message> </message>
<message> <message>
<source>Accelerating:</source> <source>Accelerating</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>Bouncing:</source> <source>Decelerating</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>Decelerating:</source> <source>Bouncing</source>
<translation></translation> <translation></translation>
</message> </message>
</context> </context>
<context> <context>
@ -807,6 +807,10 @@ Tips:
<source>Transparency</source> <source>Transparency</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<source>Countershaded</source>
<translation></translation>
</message>
</context> </context>
<context> <context>
<name>PoseEditWidget</name> <name>PoseEditWidget</name>

View File

@ -1081,6 +1081,8 @@ void Document::toSnapshot(Snapshot *snapshot, const std::set<QUuid> &limitNodeId
part["name"] = partIt.second.name; part["name"] = partIt.second.name;
if (partIt.second.materialAdjusted()) if (partIt.second.materialAdjusted())
part["materialId"] = partIt.second.materialId.toString(); part["materialId"] = partIt.second.materialId.toString();
if (partIt.second.countershaded)
part["countershaded"] = "true";
snapshot->parts[part["id"]] = part; snapshot->parts[part["id"]] = part;
} }
for (const auto &nodeIt: nodeMap) { for (const auto &nodeIt: nodeMap) {
@ -1386,6 +1388,7 @@ void Document::addFromSnapshot(const Snapshot &snapshot, bool fromPaste)
const auto &materialIdIt = partKv.second.find("materialId"); const auto &materialIdIt = partKv.second.find("materialId");
if (materialIdIt != partKv.second.end()) if (materialIdIt != partKv.second.end())
part.materialId = oldNewIdMap[QUuid(materialIdIt->second)]; part.materialId = oldNewIdMap[QUuid(materialIdIt->second)];
part.countershaded = isTrueValueString(valueOfKeyInMapOrEmpty(partKv.second, "countershaded"));
newAddedPartIds.insert(part.id); newAddedPartIds.insert(part.id);
} }
for (const auto &it: cutFaceLinkedIdModifyMap) { for (const auto &it: cutFaceLinkedIdModifyMap) {
@ -2744,6 +2747,21 @@ void Document::setPartHollowThickness(QUuid partId, float hollowThickness)
emit skeletonChanged(); emit skeletonChanged();
} }
void Document::setPartCountershaded(QUuid partId, bool countershaded)
{
auto part = partMap.find(partId);
if (part == partMap.end()) {
qDebug() << "Part not found:" << partId;
return;
}
if (part->second.countershaded == countershaded)
return;
part->second.countershaded = countershaded;
part->second.dirty = true;
emit partCountershadeStateChanged(partId);
emit textureChanged();
}
void Document::setPartCutRotation(QUuid partId, float cutRotation) void Document::setPartCutRotation(QUuid partId, float cutRotation)
{ {
auto part = partMap.find(partId); auto part = partMap.find(partId);

View File

@ -434,6 +434,7 @@ signals:
void partTargetChanged(QUuid partId); void partTargetChanged(QUuid partId);
void partColorSolubilityChanged(QUuid partId); void partColorSolubilityChanged(QUuid partId);
void partHollowThicknessChanged(QUuid partId); void partHollowThicknessChanged(QUuid partId);
void partCountershadeStateChanged(QUuid partId);
void componentCombineModeChanged(QUuid componentId); void componentCombineModeChanged(QUuid componentId);
void cleanup(); void cleanup();
void cleanupScript(); void cleanupScript();
@ -622,6 +623,7 @@ public slots:
void setPartTarget(QUuid partId, PartTarget target); void setPartTarget(QUuid partId, PartTarget target);
void setPartColorSolubility(QUuid partId, float solubility); void setPartColorSolubility(QUuid partId, float solubility);
void setPartHollowThickness(QUuid partId, float hollowThickness); void setPartHollowThickness(QUuid partId, float hollowThickness);
void setPartCountershaded(QUuid partId, bool countershaded);
void setComponentCombineMode(QUuid componentId, CombineMode combineMode); void setComponentCombineMode(QUuid componentId, CombineMode combineMode);
void moveComponentUp(QUuid componentId); void moveComponentUp(QUuid componentId);
void moveComponentDown(QUuid componentId); void moveComponentDown(QUuid componentId);

View File

@ -1018,6 +1018,7 @@ DocumentWindow::DocumentWindow() :
connect(m_document, &Document::partHollowThicknessChanged, partTreeWidget, &PartTreeWidget::partHollowThicknessChanged); connect(m_document, &Document::partHollowThicknessChanged, partTreeWidget, &PartTreeWidget::partHollowThicknessChanged);
connect(m_document, &Document::partMaterialIdChanged, partTreeWidget, &PartTreeWidget::partMaterialIdChanged); connect(m_document, &Document::partMaterialIdChanged, partTreeWidget, &PartTreeWidget::partMaterialIdChanged);
connect(m_document, &Document::partColorSolubilityChanged, partTreeWidget, &PartTreeWidget::partColorSolubilityChanged); connect(m_document, &Document::partColorSolubilityChanged, partTreeWidget, &PartTreeWidget::partColorSolubilityChanged);
connect(m_document, &Document::partCountershadeStateChanged, partTreeWidget, &PartTreeWidget::partCountershadeStateChanged);
connect(m_document, &Document::partRemoved, partTreeWidget, &PartTreeWidget::partRemoved); connect(m_document, &Document::partRemoved, partTreeWidget, &PartTreeWidget::partRemoved);
connect(m_document, &Document::cleanup, partTreeWidget, &PartTreeWidget::removeAllContent); connect(m_document, &Document::cleanup, partTreeWidget, &PartTreeWidget::removeAllContent);
connect(m_document, &Document::partChecked, partTreeWidget, &PartTreeWidget::partChecked); connect(m_document, &Document::partChecked, partTreeWidget, &PartTreeWidget::partChecked);

View File

@ -40,7 +40,7 @@ int main(int argc, char ** argv)
darkPalette.setColor(QPalette::BrightText, Theme::red); darkPalette.setColor(QPalette::BrightText, Theme::red);
darkPalette.setColor(QPalette::Link, QColor(42, 130, 218)); darkPalette.setColor(QPalette::Link, QColor(42, 130, 218));
darkPalette.setColor(QPalette::Highlight, Theme::red); darkPalette.setColor(QPalette::Highlight, Theme::red);
darkPalette.setColor(QPalette::HighlightedText, Theme::black); darkPalette.setColor(QPalette::HighlightedText, Theme::black);
qApp->setPalette(darkPalette); qApp->setPalette(darkPalette);
//qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #fc6621; border: 1px solid white; }"); //qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #fc6621; border: 1px solid white; }");

View File

@ -587,6 +587,7 @@ nodemesh::Combiner::Mesh *MeshGenerator::combinePartMesh(const QString &partIdSt
const auto &originNodeIdString = nodeIndexToIdStringMap[node.originNodeIndex]; const auto &originNodeIdString = nodeIndexToIdStringMap[node.originNodeIndex];
OutcomePaintNode paintNode; OutcomePaintNode paintNode;
paintNode.originNodeIndex = node.originNodeIndex;
paintNode.originNodeId = QUuid(originNodeIdString); paintNode.originNodeId = QUuid(originNodeIdString);
paintNode.radius = node.radius; paintNode.radius = node.radius;
paintNode.origin = node.position; paintNode.origin = node.position;
@ -615,6 +616,8 @@ nodemesh::Combiner::Mesh *MeshGenerator::combinePartMesh(const QString &partIdSt
paintNode.baseNormal = builder->nodeBaseNormal(i); paintNode.baseNormal = builder->nodeBaseNormal(i);
paintNode.direction = builder->nodeTraverseDirection(i); paintNode.direction = builder->nodeTraverseDirection(i);
paintNode.order = builder->nodeTraverseOrder(i); paintNode.order = builder->nodeTraverseOrder(i);
partCache.outcomeNodes[paintNode.originNodeIndex].direction = paintNode.direction;
} }
bool hasMeshError = false; bool hasMeshError = false;

View File

@ -193,9 +193,20 @@ void MotionTimelineWidget::showInterpolationSettingPopup(int clipIndex, const QP
QWidget *cubicWidget = new QWidget; QWidget *cubicWidget = new QWidget;
QCheckBox *hasAcceleratingBox = new QCheckBox(); QCheckBox *hasAcceleratingBox = new QCheckBox();
hasAcceleratingBox->setText(tr("Accelerating"));
Theme::initCheckbox(hasAcceleratingBox);
QCheckBox *hasDeceleratingBox = new QCheckBox(); QCheckBox *hasDeceleratingBox = new QCheckBox();
hasDeceleratingBox->setText(tr("Decelerating"));
Theme::initCheckbox(hasDeceleratingBox);
QCheckBox *bouncingBeginBox = new QCheckBox(); QCheckBox *bouncingBeginBox = new QCheckBox();
bouncingBeginBox->setText(tr("Bouncing"));
Theme::initCheckbox(bouncingBeginBox);
QCheckBox *bouncingEndBox = new QCheckBox(); QCheckBox *bouncingEndBox = new QCheckBox();
bouncingEndBox->setText(tr("Bouncing"));
Theme::initCheckbox(bouncingEndBox);
QStackedWidget *stackedWidget = new QStackedWidget; QStackedWidget *stackedWidget = new QStackedWidget;
stackedWidget->addWidget(linearWidget); stackedWidget->addWidget(linearWidget);
@ -271,29 +282,13 @@ void MotionTimelineWidget::showInterpolationSettingPopup(int clipIndex, const QP
QVBoxLayout *cubicLayout = new QVBoxLayout; QVBoxLayout *cubicLayout = new QVBoxLayout;
QHBoxLayout *acceleratingLayout = new QHBoxLayout; QHBoxLayout *acceleratingLayout = new QHBoxLayout;
{ acceleratingLayout->addWidget(hasAcceleratingBox);
QFormLayout *formLayout = new QFormLayout; acceleratingLayout->addWidget(bouncingBeginBox);
formLayout->addRow(tr("Accelerating:"), hasAcceleratingBox);
acceleratingLayout->addLayout(formLayout);
}
{
QFormLayout *formLayout = new QFormLayout;
formLayout->addRow(tr("Bouncing:"), bouncingBeginBox);
acceleratingLayout->addLayout(formLayout);
}
cubicLayout->addLayout(acceleratingLayout); cubicLayout->addLayout(acceleratingLayout);
QHBoxLayout *deceleratingLayout = new QHBoxLayout; QHBoxLayout *deceleratingLayout = new QHBoxLayout;
{ deceleratingLayout->addWidget(hasDeceleratingBox);
QFormLayout *formLayout = new QFormLayout; deceleratingLayout->addWidget(bouncingEndBox);
formLayout->addRow(tr("Decelerating:"), hasDeceleratingBox);
deceleratingLayout->addLayout(formLayout);
}
{
QFormLayout *formLayout = new QFormLayout;
formLayout->addRow(tr("Bouncing:"), bouncingEndBox);
deceleratingLayout->addLayout(formLayout);
}
cubicLayout->addLayout(deceleratingLayout); cubicLayout->addLayout(deceleratingLayout);
cubicWidget->setLayout(cubicLayout); cubicWidget->setLayout(cubicLayout);

View File

@ -23,10 +23,12 @@ struct OutcomeNode
QUuid mirrorFromPartId; QUuid mirrorFromPartId;
QUuid mirroredByPartId; QUuid mirroredByPartId;
BoneMark boneMark; BoneMark boneMark;
QVector3D direction;
}; };
struct OutcomePaintNode struct OutcomePaintNode
{ {
int originNodeIndex;
QUuid originNodeId; QUuid originNodeId;
QVector3D origin; QVector3D origin;
float radius = 0; float radius = 0;

View File

@ -1046,6 +1046,17 @@ void PartTreeWidget::partColorSolubilityChanged(QUuid partId)
widget->updateColorButton(); widget->updateColorButton();
} }
void PartTreeWidget::partCountershadeStateChanged(QUuid partId)
{
auto item = m_partItemMap.find(partId);
if (item == m_partItemMap.end()) {
qDebug() << "Part item not found:" << partId;
return;
}
PartWidget *widget = (PartWidget *)itemWidget(item->second, 0);
widget->updateColorButton();
}
void PartTreeWidget::partChecked(QUuid partId) void PartTreeWidget::partChecked(QUuid partId)
{ {
auto item = m_partItemMap.find(partId); auto item = m_partItemMap.find(partId);

View File

@ -71,6 +71,7 @@ public slots:
void partHollowThicknessChanged(QUuid partId); void partHollowThicknessChanged(QUuid partId);
void partMaterialIdChanged(QUuid partId); void partMaterialIdChanged(QUuid partId);
void partColorSolubilityChanged(QUuid partId); void partColorSolubilityChanged(QUuid partId);
void partCountershadeStateChanged(QUuid partId);
void partChecked(QUuid partId); void partChecked(QUuid partId);
void partUnchecked(QUuid partId); void partUnchecked(QUuid partId);
void partComponentChecked(QUuid partId); void partComponentChecked(QUuid partId);

View File

@ -7,6 +7,7 @@
#include <QSizePolicy> #include <QSizePolicy>
#include <QFileDialog> #include <QFileDialog>
#include <QSizePolicy> #include <QSizePolicy>
#include <QCheckBox>
#include <nodemesh/misc.h> #include <nodemesh/misc.h>
#include "partwidget.h" #include "partwidget.h"
#include "theme.h" #include "theme.h"
@ -172,6 +173,7 @@ PartWidget::PartWidget(const Document *document, QUuid partId) :
connect(this, &PartWidget::setPartMaterialId, m_document, &Document::setPartMaterialId); connect(this, &PartWidget::setPartMaterialId, m_document, &Document::setPartMaterialId);
connect(this, &PartWidget::setPartColorSolubility, m_document, &Document::setPartColorSolubility); connect(this, &PartWidget::setPartColorSolubility, m_document, &Document::setPartColorSolubility);
connect(this, &PartWidget::setPartHollowThickness, m_document, &Document::setPartHollowThickness); connect(this, &PartWidget::setPartHollowThickness, m_document, &Document::setPartHollowThickness);
connect(this, &PartWidget::setPartCountershaded, m_document, &Document::setPartCountershaded);
connect(this, &PartWidget::checkPart, m_document, &Document::checkPart); connect(this, &PartWidget::checkPart, m_document, &Document::checkPart);
connect(this, &PartWidget::enableBackgroundBlur, m_document, &Document::enableBackgroundBlur); connect(this, &PartWidget::enableBackgroundBlur, m_document, &Document::enableBackgroundBlur);
connect(this, &PartWidget::disableBackgroundBlur, m_document, &Document::disableBackgroundBlur); connect(this, &PartWidget::disableBackgroundBlur, m_document, &Document::disableBackgroundBlur);
@ -361,10 +363,21 @@ void PartWidget::showColorSettingPopup(const QPoint &pos)
palette.setColor(QPalette::Button, choosenColor); palette.setColor(QPalette::Button, choosenColor);
pickButton->setPalette(palette); pickButton->setPalette(palette);
QCheckBox *countershadeStateBox = new QCheckBox();
Theme::initCheckbox(countershadeStateBox);
countershadeStateBox->setText(tr("Countershaded"));
countershadeStateBox->setChecked(part->countershaded);
connect(countershadeStateBox, &QCheckBox::stateChanged, this, [=]() {
emit setPartCountershaded(m_partId, countershadeStateBox->isChecked());
emit groupOperationAdded();
});
QHBoxLayout *colorLayout = new QHBoxLayout; QHBoxLayout *colorLayout = new QHBoxLayout;
colorLayout->addWidget(colorEraser); colorLayout->addWidget(colorEraser);
colorLayout->addWidget(pickButton); colorLayout->addWidget(pickButton);
colorLayout->addStretch(); colorLayout->addStretch();
colorLayout->addWidget(countershadeStateBox);
connect(colorEraser, &QPushButton::clicked, [=]() { connect(colorEraser, &QPushButton::clicked, [=]() {
emit setPartColorState(m_partId, false, Qt::white); emit setPartColorState(m_partId, false, Qt::white);
@ -894,7 +907,7 @@ void PartWidget::updateColorButton()
qDebug() << "Part not found:" << m_partId; qDebug() << "Part not found:" << m_partId;
return; return;
} }
if (part->hasColor || part->materialAdjusted() || part->colorSolubilityAdjusted()) if (part->hasColor || part->materialAdjusted() || part->colorSolubilityAdjusted() || part->countershaded)
updateButton(m_colorButton, QChar(fa::eyedropper), true); updateButton(m_colorButton, QChar(fa::eyedropper), true);
else else
updateButton(m_colorButton, QChar(fa::eyedropper), false); updateButton(m_colorButton, QChar(fa::eyedropper), false);

View File

@ -29,6 +29,7 @@ signals:
void setPartMaterialId(QUuid partId, QUuid materialId); void setPartMaterialId(QUuid partId, QUuid materialId);
void setPartColorSolubility(QUuid partId, float colorSolubility); void setPartColorSolubility(QUuid partId, float colorSolubility);
void setPartHollowThickness(QUuid partId, float hollowThickness); void setPartHollowThickness(QUuid partId, float hollowThickness);
void setPartCountershaded(QUuid partId, bool countershaded);
void movePartUp(QUuid partId); void movePartUp(QUuid partId);
void movePartDown(QUuid partId); void movePartDown(QUuid partId);
void movePartToTop(QUuid partId); void movePartToTop(QUuid partId);

View File

@ -58,11 +58,13 @@ PreferencesWidget::PreferencesWidget(const Document *document, QWidget *parent)
}); });
QCheckBox *flatShadingBox = new QCheckBox(); QCheckBox *flatShadingBox = new QCheckBox();
Theme::initCheckbox(flatShadingBox);
connect(flatShadingBox, &QCheckBox::stateChanged, this, [=]() { connect(flatShadingBox, &QCheckBox::stateChanged, this, [=]() {
Preferences::instance().setFlatShading(flatShadingBox->isChecked()); Preferences::instance().setFlatShading(flatShadingBox->isChecked());
}); });
QCheckBox *threeNodesBranchEnabledBox = new QCheckBox(); QCheckBox *threeNodesBranchEnabledBox = new QCheckBox();
Theme::initCheckbox(threeNodesBranchEnabledBox);
connect(threeNodesBranchEnabledBox, &QCheckBox::stateChanged, this, [=]() { connect(threeNodesBranchEnabledBox, &QCheckBox::stateChanged, this, [=]() {
Preferences::instance().setThreeNodesBranchEnableState(threeNodesBranchEnabledBox->isChecked()); Preferences::instance().setThreeNodesBranchEnableState(threeNodesBranchEnabledBox->isChecked());
}); });

View File

@ -87,6 +87,7 @@ void ScriptVariablesWidget::reload()
auto defaultValue = isTrueValueString(valueOfKeyInMapOrEmpty(variable.second, "defaultValue")); auto defaultValue = isTrueValueString(valueOfKeyInMapOrEmpty(variable.second, "defaultValue"));
QCheckBox *checkBox = new QCheckBox; QCheckBox *checkBox = new QCheckBox;
Theme::initCheckbox(checkBox);
checkBox->setText(name); checkBox->setText(name);
checkBox->setChecked(value); checkBox->setChecked(value);

View File

@ -178,6 +178,7 @@ public:
float deformMapScale; float deformMapScale;
QUuid deformMapImageId; QUuid deformMapImageId;
float hollowThickness; float hollowThickness;
bool countershaded;
SkeletonPart(const QUuid &withId=QUuid()) : SkeletonPart(const QUuid &withId=QUuid()) :
visible(true), visible(true),
locked(false), locked(false),
@ -198,7 +199,8 @@ public:
target(PartTarget::Model), target(PartTarget::Model),
colorSolubility(0.0), colorSolubility(0.0),
deformMapScale(1.0), deformMapScale(1.0),
hollowThickness(0.0) hollowThickness(0.0),
countershaded(false)
{ {
id = withId.isNull() ? QUuid::createUuid() : withId; id = withId.isNull() ? QUuid::createUuid() : withId;
} }
@ -311,6 +313,7 @@ public:
materialId = other.materialId; materialId = other.materialId;
target = other.target; target = other.target;
colorSolubility = other.colorSolubility; colorSolubility = other.colorSolubility;
countershaded = other.countershaded;
} }
void updatePreviewMesh(MeshLoader *previewMesh) void updatePreviewMesh(MeshLoader *previewMesh)
{ {

View File

@ -171,6 +171,8 @@ void TextureGenerator::prepare()
materialId = QUuid(materialIdIt->second); materialId = QUuid(materialIdIt->second);
QUuid partId = QUuid(partIt.first); QUuid partId = QUuid(partIt.first);
updatedMaterialIdMap.insert({partId, materialId}); updatedMaterialIdMap.insert({partId, materialId});
if (isTrueValueString(valueOfKeyInMapOrEmpty(partIt.second, "countershaded")))
m_countershadedPartIds.insert(partId);
} }
for (const auto &bmeshNode: m_outcome->nodes) { for (const auto &bmeshNode: m_outcome->nodes) {
for (size_t i = 0; i < (int)TextureType::Count - 1; ++i) { for (size_t i = 0; i < (int)TextureType::Count - 1; ++i) {
@ -221,6 +223,7 @@ void TextureGenerator::generate()
const auto &triangleVertexUvs = *m_outcome->triangleVertexUvs(); const auto &triangleVertexUvs = *m_outcome->triangleVertexUvs();
const auto &triangleSourceNodes = *m_outcome->triangleSourceNodes(); const auto &triangleSourceNodes = *m_outcome->triangleSourceNodes();
const auto &partUvRects = *m_outcome->partUvRects(); const auto &partUvRects = *m_outcome->partUvRects();
const auto &triangleNormals = m_outcome->triangleNormals;
std::map<QUuid, QColor> partColorMap; std::map<QUuid, QColor> partColorMap;
std::map<std::pair<QUuid, QUuid>, const OutcomeNode *> nodeMap; std::map<std::pair<QUuid, QUuid>, const OutcomeNode *> nodeMap;
@ -382,7 +385,7 @@ void TextureGenerator::generate()
drawTexture(partRoughnessTexturePixmaps, textureRoughnessPainter, false); drawTexture(partRoughnessTexturePixmaps, textureRoughnessPainter, false);
drawTexture(partAmbientOcclusionTexturePixmaps, textureAmbientOcclusionPainter, false); drawTexture(partAmbientOcclusionTexturePixmaps, textureAmbientOcclusionPainter, false);
auto drawGradient = [&](const QUuid &partId, size_t triangleIndex, size_t firstVertexIndex, size_t secondVertexIndex, auto drawBySolubility = [&](const QUuid &partId, size_t triangleIndex, size_t firstVertexIndex, size_t secondVertexIndex,
const QUuid &neighborPartId) { const QUuid &neighborPartId) {
const std::vector<QVector2D> &uv = triangleVertexUvs[triangleIndex]; const std::vector<QVector2D> &uv = triangleVertexUvs[triangleIndex];
const auto &allRects = partUvRects.find(partId); const auto &allRects = partUvRects.find(partId);
@ -495,8 +498,110 @@ void TextureGenerator::generate()
const std::pair<QUuid, QUuid> &oppositeSource = triangleSourceNodes[std::get<0>(opposite->second)]; const std::pair<QUuid, QUuid> &oppositeSource = triangleSourceNodes[std::get<0>(opposite->second)];
if (source.first == oppositeSource.first) if (source.first == oppositeSource.first)
continue; continue;
drawGradient(source.first, std::get<0>(it.second), std::get<1>(it.second), std::get<2>(it.second), oppositeSource.first); drawBySolubility(source.first, std::get<0>(it.second), std::get<1>(it.second), std::get<2>(it.second), oppositeSource.first);
drawGradient(oppositeSource.first, std::get<0>(opposite->second), std::get<1>(opposite->second), std::get<2>(opposite->second), source.first); drawBySolubility(oppositeSource.first, std::get<0>(opposite->second), std::get<1>(opposite->second), std::get<2>(opposite->second), source.first);
}
// Draw belly white
texturePainter.setCompositionMode(QPainter::CompositionMode_SoftLight);
for (size_t triangleIndex = 0; triangleIndex < m_outcome->triangles.size(); ++triangleIndex) {
const auto &normal = triangleNormals[triangleIndex];
const std::pair<QUuid, QUuid> &source = triangleSourceNodes[triangleIndex];
const auto &partId = source.first;
if (m_countershadedPartIds.find(partId) == m_countershadedPartIds.end())
continue;
const auto &allRects = partUvRects.find(partId);
if (allRects == partUvRects.end()) {
qDebug() << "Found part uv rects failed";
continue;
}
const auto &findOutcomeNode = nodeMap.find(source);
if (findOutcomeNode == nodeMap.end())
continue;
const OutcomeNode *outcomeNode = findOutcomeNode->second;
if (qAbs(QVector3D::dotProduct(outcomeNode->direction, QVector3D(0, 1, 0))) >= 0.707) {
if (QVector3D::dotProduct(normal, QVector3D(0, 0, 1)) <= 0.0)
continue;
} else {
if (QVector3D::dotProduct(normal, QVector3D(0, -1, 0)) <= 0.0)
continue;
}
const auto &triangleIndices = m_outcome->triangles[triangleIndex];
if (triangleIndices.size() != 3) {
qDebug() << "Found invalid triangle indices";
continue;
}
const std::vector<QVector2D> &uv = triangleVertexUvs[triangleIndex];
QVector2D middlePoint = (uv[0] + uv[1] + uv[2]) / 3.0;
float finalRadius = (uv[0].distanceToPoint(uv[1]) +
uv[1].distanceToPoint(uv[2]) +
uv[2].distanceToPoint(uv[0])) / 3.0;
QRadialGradient gradient(QPointF(middlePoint.x() * TextureGenerator::m_textureSize,
middlePoint.y() * TextureGenerator::m_textureSize),
finalRadius * TextureGenerator::m_textureSize);
gradient.setColorAt(0.0, Qt::white);
gradient.setColorAt(1.0, Qt::transparent);
for (const auto &it: allRects->second) {
if (it.contains(middlePoint.x(), middlePoint.y())) {
QRectF fillTarget((middlePoint.x() - finalRadius),
(middlePoint.y() - finalRadius),
(finalRadius + finalRadius),
(finalRadius + finalRadius));
auto clippedRect = it.intersected(fillTarget);
QRectF translatedRect = {
clippedRect.left() * TextureGenerator::m_textureSize,
clippedRect.top() * TextureGenerator::m_textureSize,
clippedRect.width() * TextureGenerator::m_textureSize,
clippedRect.height() * TextureGenerator::m_textureSize
};
texturePainter.fillRect(translatedRect, gradient);
}
}
// Fill the neighbor halfedges
for (int i = 0; i < 3; ++i) {
int j = (i + 1) % 3;
auto oppositeHalfEdge = std::make_pair(triangleIndices[j], triangleIndices[i]);
const auto &opposite = halfEdgeToTriangleMap.find(oppositeHalfEdge);
if (opposite == halfEdgeToTriangleMap.end())
continue;
auto oppositeTriangleIndex = std::get<0>(opposite->second);
const std::pair<QUuid, QUuid> &oppositeSource = triangleSourceNodes[oppositeTriangleIndex];
if (partId == oppositeSource.first)
continue;
const auto &oppositeAllRects = partUvRects.find(oppositeSource.first);
if (oppositeAllRects == partUvRects.end()) {
qDebug() << "Found part uv rects failed";
continue;
}
const std::vector<QVector2D> &oppositeUv = triangleVertexUvs[oppositeTriangleIndex];
QVector2D oppositeMiddlePoint = (oppositeUv[std::get<1>(opposite->second)] + oppositeUv[std::get<2>(opposite->second)]) * 0.5;
QRadialGradient oppositeGradient(QPointF(oppositeMiddlePoint.x() * TextureGenerator::m_textureSize,
oppositeMiddlePoint.y() * TextureGenerator::m_textureSize),
finalRadius * TextureGenerator::m_textureSize);
oppositeGradient.setColorAt(0.0, Qt::white);
oppositeGradient.setColorAt(1.0, Qt::transparent);
for (const auto &it: oppositeAllRects->second) {
if (it.contains(oppositeMiddlePoint.x(), oppositeMiddlePoint.y())) {
QRectF fillTarget((oppositeMiddlePoint.x() - finalRadius),
(oppositeMiddlePoint.y() - finalRadius),
(finalRadius + finalRadius),
(finalRadius + finalRadius));
auto clippedRect = it.intersected(fillTarget);
QRectF translatedRect = {
clippedRect.left() * TextureGenerator::m_textureSize,
clippedRect.top() * TextureGenerator::m_textureSize,
clippedRect.width() * TextureGenerator::m_textureSize,
clippedRect.height() * TextureGenerator::m_textureSize
};
texturePainter.fillRect(translatedRect, oppositeGradient);
}
}
}
} }
hasNormalMap = !m_partNormalTextureMap.empty(); hasNormalMap = !m_partNormalTextureMap.empty();

View File

@ -58,6 +58,7 @@ private:
std::map<QUuid, std::pair<QImage, float>> m_partMetalnessTextureMap; std::map<QUuid, std::pair<QImage, float>> m_partMetalnessTextureMap;
std::map<QUuid, std::pair<QImage, float>> m_partRoughnessTextureMap; std::map<QUuid, std::pair<QImage, float>> m_partRoughnessTextureMap;
std::map<QUuid, std::pair<QImage, float>> m_partAmbientOcclusionTextureMap; std::map<QUuid, std::pair<QImage, float>> m_partAmbientOcclusionTextureMap;
std::set<QUuid> m_countershadedPartIds;
Snapshot *m_snapshot; Snapshot *m_snapshot;
}; };

View File

@ -177,6 +177,13 @@ void Theme::initToolButton(QPushButton *button)
button->setFocusPolicy(Qt::NoFocus); button->setFocusPolicy(Qt::NoFocus);
} }
void Theme::initCheckbox(QCheckBox *checkbox)
{
QPalette palette = checkbox->palette();
palette.setColor(QPalette::Background, Theme::white);
checkbox->setPalette(palette);
}
QWidget *Theme::createHorizontalLineWidget() QWidget *Theme::createHorizontalLineWidget()
{ {
QWidget *hrLightWidget = new QWidget; QWidget *hrLightWidget = new QWidget;

View File

@ -5,6 +5,7 @@
#include <map> #include <map>
#include <QPushButton> #include <QPushButton>
#include <QLabel> #include <QLabel>
#include <QCheckBox>
#include "QtAwesome.h" #include "QtAwesome.h"
class Theme class Theme
@ -53,6 +54,7 @@ public:
static void initAwesomeToolButtonWithoutFont(QPushButton *button); static void initAwesomeToolButtonWithoutFont(QPushButton *button);
static void initAwsomeBaseSizes(); static void initAwsomeBaseSizes();
static void initToolButton(QPushButton *button); static void initToolButton(QPushButton *button);
static void initCheckbox(QCheckBox *checkbox);
}; };
#endif #endif