Compare commits
2 Commits
97097fcc3a
...
cf3dd43a4a
Author | SHA1 | Date |
---|---|---|
wuyize | cf3dd43a4a | |
wuyize | 62b9c2b026 |
|
@ -969,7 +969,7 @@ void drawLine(in float d, inout uint styleIndex, out vec4 elementColor, out vec2
|
|||
}
|
||||
}
|
||||
|
||||
bool shouldFillBeginCap(vec2 localUV, bool onVeryBegin, int endType, vec2 p3, vec2 tangentBegin, vec2 tangentEndLast)
|
||||
bool shouldFillBeginCap(vec2 localUV, bool onVeryBegin, int endType, vec2 p0, vec2 tangentBegin, vec2 tangentEndLast)
|
||||
{
|
||||
vec2 normal;
|
||||
if (onVeryBegin)
|
||||
|
@ -985,17 +985,26 @@ bool shouldFillBeginCap(vec2 localUV, bool onVeryBegin, int endType, vec2 p3, ve
|
|||
vec2 normalNow = normalize(mat2(0, 1, -1, 0) * (-tangentBegin));
|
||||
normal = normalLast + normalNow;
|
||||
}
|
||||
return angleLargeThanPi(normal, localUV - p3);
|
||||
return angleLargeThanPi(normal, localUV - p0);
|
||||
}
|
||||
|
||||
bool shouldFillEndCap(vec2 localUV, int endType, vec2 p0, vec2 tangentEnd)
|
||||
bool shouldFillEndCap(vec2 localUV, bool onVeryEnd, int endType, vec2 p3, vec2 tangentEnd, vec2 tangentBeginNext)
|
||||
{
|
||||
vec2 normal;
|
||||
if (endType == 0)
|
||||
return true;
|
||||
else if (endType == 1)
|
||||
normal = normalize(mat2(0, 1, -1, 0) * tangentEnd);
|
||||
return angleLargeThanPi(localUV - p0, normal);
|
||||
if (onVeryEnd)
|
||||
{
|
||||
if (endType == 0)
|
||||
return true;
|
||||
else if (endType == 1)
|
||||
normal = normalize(mat2(0, 1, -1, 0) * tangentEnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
vec2 normalLast = normalize(mat2(0, 1, -1, 0) * tangentEnd);
|
||||
vec2 normalNow = normalize(mat2(0, 1, -1, 0) * (-tangentBeginNext));
|
||||
normal = normalLast + normalNow;
|
||||
}
|
||||
return angleLargeThanPi(localUV - p3, normal);
|
||||
}
|
||||
|
||||
void main()
|
||||
|
@ -1055,21 +1064,25 @@ void main()
|
|||
float lineType = floor(styleHead.b * 10);
|
||||
// float lineType = 2;
|
||||
int endType = int(round(styleHead.b * 100)) % 10;
|
||||
//endType = 1;
|
||||
// endType = 1;
|
||||
int debugBegin = 0;
|
||||
bool onVeryBegin = false;
|
||||
bool onVeryEnd = false;
|
||||
vec2 tangentEndLast;
|
||||
uint lastHitIndex = 0;
|
||||
bool lastHitElement = false;
|
||||
hitElement = false;
|
||||
for (uint pathIndex = 0; pathIndex < pathSize; pathIndex++)
|
||||
// for (uint pathIndex = 0; pathIndex < 4; pathIndex++)
|
||||
//for (uint pathIndex = 0; pathIndex < 46; pathIndex++)
|
||||
{
|
||||
vec2 pTemp = path[pathIndex];
|
||||
if (isinf(pTemp.x))
|
||||
{
|
||||
// TODO: ¼ì²âÊÇ·ñ·â±Õ²¢´¦Àí
|
||||
if (hitElement && distance(localUV, p3Last) <= strokeWidth)
|
||||
{
|
||||
hitElement = shouldFillEndCap(localUV, endType, p3Last, tangentEndLast);
|
||||
}
|
||||
if (hitElement && distance(localUV, p3Last) <= strokeWidth)
|
||||
{
|
||||
// hitElement = shouldFillEndCap(localUV, true, endType, p3Last, tangentEndLast);
|
||||
}
|
||||
|
||||
pBegin = path[++pathIndex];
|
||||
p3Last = pBegin;
|
||||
|
@ -1079,10 +1092,30 @@ void main()
|
|||
}
|
||||
mat4x2 p = mat4x2(p3Last, pTemp, path[++pathIndex], path[++pathIndex]);
|
||||
|
||||
vec2 tangentBeginNext;
|
||||
if (pathIndex + 1 < pathSize)
|
||||
{
|
||||
vec2 pTemp = path[pathIndex + 1];
|
||||
if (isinf(pTemp.x))
|
||||
{
|
||||
onVeryEnd = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
onVeryEnd = false;
|
||||
vec2 pNext[3] = {p[3], pTemp, path[pathIndex + 2]};
|
||||
if (pNext[0] != pNext[1])
|
||||
tangentBeginNext = normalize(pNext[0] - pNext[1]);
|
||||
else
|
||||
tangentBeginNext = normalize(pNext[0] - pNext[2]);
|
||||
}
|
||||
}
|
||||
|
||||
float d = cubic_bezier_dis(localUV, p[0], p[1], p[2], p[3], true);
|
||||
if (d <= strokeWidth)
|
||||
{
|
||||
bool onBegin = distance(localUV, p[0]) <= strokeWidth && p3Last == p[0];
|
||||
bool onBegin = distance(localUV, p[0]) <= strokeWidth;
|
||||
bool onEnd = distance(localUV, p[3]) <= strokeWidth;
|
||||
vec2 tangentBegin;
|
||||
vec2 tangentEnd;
|
||||
if (p[0] != p[1])
|
||||
|
@ -1094,11 +1127,19 @@ void main()
|
|||
else
|
||||
tangentEnd = normalize(p[3] - p[1]);
|
||||
|
||||
if (onBegin ? shouldFillBeginCap(localUV, onVeryBegin, endType, p[0], tangentBegin, p3Last - p2Last)
|
||||
: d < minDistance)
|
||||
// if (onBegin ? shouldFillBeginCap(localUV, onVeryBegin, endType, p[0], tangentBegin,
|
||||
// tangentEndLast)
|
||||
// : (onEnd ? /*shouldFillEndCap(localUV, onVeryEnd, endType, p[3], tangentEnd,
|
||||
// tangentBeginNext)*/ false
|
||||
// : d < minDistance))
|
||||
bool hit = d < minDistance;
|
||||
if (onBegin)
|
||||
hit = hit &&
|
||||
shouldFillBeginCap(localUV, onVeryBegin, endType, p[0], tangentBegin, tangentEndLast);
|
||||
if (onEnd)
|
||||
hit = hit && shouldFillEndCap(localUV, onVeryEnd, endType, p[3], tangentEnd, tangentBeginNext);
|
||||
if (hit)
|
||||
{
|
||||
minDistance = min(minDistance, d);
|
||||
|
||||
bool reverse = p[3].y - p[0].y < 0.;
|
||||
|
||||
if (tangentBegin.y == 0.)
|
||||
|
@ -1111,13 +1152,26 @@ void main()
|
|||
|
||||
if (lineType == 2 || (intTest % 2 == int(lineType)))
|
||||
{
|
||||
minDistance = min(minDistance, d);
|
||||
lastHitElement = hitElement;
|
||||
lastHitIndex = pathIndex;
|
||||
hitElement = true;
|
||||
// elementColor = vec4(1, 1, 0, 1);
|
||||
vec2 metallicRoughness;
|
||||
drawLine(minDistance / strokeWidth, styleIndex, elementColor, metallicRoughness);
|
||||
}
|
||||
else if (p3Last == p[0])
|
||||
hitElement = false;
|
||||
// else if (lastHitIndex == pathIndex - 3)
|
||||
// {
|
||||
// hitElement = lastHitElement;
|
||||
// lastHitElement = false;
|
||||
// // if(lastHitElement ==false)
|
||||
// //{
|
||||
// // hitElement = true;
|
||||
// // elementColor = vec4(1, 1, 0, 1);
|
||||
// //}
|
||||
|
||||
// minDistance = 1e38;
|
||||
// }
|
||||
}
|
||||
tangentEndLast = tangentEnd;
|
||||
}
|
||||
|
@ -1127,7 +1181,7 @@ void main()
|
|||
}
|
||||
if (hitElement && distance(localUV, p3Last) <= strokeWidth)
|
||||
{
|
||||
hitElement = shouldFillEndCap(localUV, endType, p3Last, tangentEndLast);
|
||||
// hitElement = shouldFillEndCap(localUV, true, endType, p3Last, tangentEndLast);
|
||||
}
|
||||
}
|
||||
if (hitElement)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -62,15 +62,15 @@ QPainterPath PainterPathUtil::monotonization(QPainterPath& painterPath) {
|
|||
return resPath;
|
||||
}
|
||||
|
||||
std::pair<QPainterPath, float> PainterPathUtil::normalized(const QPainterPath& path)
|
||||
std::pair<QPainterPath, float> PainterPathUtil::normalized(const QPainterPath& path, float width)
|
||||
{
|
||||
auto rect = path.boundingRect();
|
||||
return { (QTransform::fromTranslate(-rect.center().x(), -rect.center().y()) * QTransform::fromScale(1 / (rect.width() / 1.999999), -1 / (rect.height() / 1.999999))).map(path),
|
||||
return { (QTransform::fromTranslate(-rect.center().x(), -rect.center().y()) * QTransform::fromScale(1 / (rect.width() / 1.999999), -1 / (rect.height() / 1.999999)) * QTransform::fromScale(1 / (1 + width),1 / (1 + width))).map(path),
|
||||
rect.width() / rect.height() };
|
||||
}
|
||||
|
||||
std::pair<std::vector<std::vector<Renderer::Point>>, float> PainterPathUtil::toNormalizedLines(const QPainterPath& path)
|
||||
std::pair<std::vector<std::vector<Renderer::Point>>, float> PainterPathUtil::toNormalizedLines(const QPainterPath& path, float width)
|
||||
{
|
||||
auto [p, ratio] = normalized(path);
|
||||
auto [p, ratio] = normalized(path, width);
|
||||
return { transformToLines(p), ratio };
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ class PainterPathUtil
|
|||
public:
|
||||
static std::vector<std::vector<Renderer::Point>> transformToLines(const QPainterPath& painterPath);
|
||||
static QPainterPath monotonization(QPainterPath& painterPath);
|
||||
static std::pair<QPainterPath, float> normalized(const QPainterPath& path);
|
||||
static std::pair<std::vector<std::vector<Renderer::Point>>, float> toNormalizedLines(const QPainterPath& path);
|
||||
static std::pair<QPainterPath, float> normalized(const QPainterPath& path, float width = 0);
|
||||
static std::pair<std::vector<std::vector<Renderer::Point>>, float> toNormalizedLines(const QPainterPath& path, float width = 0);
|
||||
};
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "../Editor/util/PainterPathUtil.h"
|
||||
#include "../Editor/util/SvgFileLoader.h"
|
||||
#include <ThirdPartyLib/qquick/qquicksvgparser_p.h>
|
||||
#include "Painting/MaterialStyleStroke.h"
|
||||
|
||||
using namespace Renderer;
|
||||
using std::vector;
|
||||
|
@ -156,14 +157,13 @@ std::unique_ptr<Drawable> Model::processMesh(aiMesh* mesh, const aiScene* scene,
|
|||
|
||||
for (auto& v : vertices)
|
||||
{
|
||||
//qDebug() << v.TexCoords.x << v.TexCoords.y;
|
||||
v.TexCoords = (v.TexCoords - leftBottom) / (rightTop - leftBottom);
|
||||
qDebug() << v.TexCoords.x << v.TexCoords.y;
|
||||
//qDebug() << v.TexCoords.x << v.TexCoords.y;
|
||||
}
|
||||
|
||||
|
||||
mesh->vertices = vertices;
|
||||
mesh->indices = indices;
|
||||
|
||||
|
||||
mesh->paintingId = loadPainting(paintingPath);
|
||||
auto& handle = vtManager->getPaintingHandle(mesh->paintingId);
|
||||
mesh->textureBasecolor = handle.baseColor;
|
||||
|
@ -271,6 +271,52 @@ GLuint Renderer::Model::loadPainting(std::string path)
|
|||
painting.addElement(*element[1], ElementTransform{ glm::vec2(-0.45, 0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 });
|
||||
painting.addElement(*element[2], ElementTransform{ glm::vec2(0.50,-0.45), glm::vec2(0.6,0.7) / 2.f, 0, glm::bvec2(false), 0 });
|
||||
}
|
||||
else if (path == "1.json")
|
||||
{
|
||||
float widths[] = { 0.43, 0.43 * 0.25 / 0.15, 0.13 * 0.25 / 0.15 };
|
||||
QPainterPath painterPaths[6];
|
||||
for (int i = 0; i < 6; i++)
|
||||
if (!SvgFileLoader().loadSvgFile(QString(std::format("../svg/{}.svg", i + 1).c_str()), painterPaths[i]))
|
||||
qCritical() << "load error";
|
||||
|
||||
vector<std::pair<std::shared_ptr<Contour>, float>> contours;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
auto [contour, ratio] = PainterPathUtil::toNormalizedLines(painterPaths[i], widths[i]);
|
||||
contours.emplace_back(std::make_shared<Contour>(contour), ratio);
|
||||
}
|
||||
class StyleStrokeRadialGradient : public Renderer::ElementStyle
|
||||
{
|
||||
public:
|
||||
float width;
|
||||
StrokeType type;
|
||||
StyleStrokeRadialGradient(float width, StrokeType type) :width(width), type(type) {};
|
||||
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override
|
||||
{
|
||||
std::map<float, Material> materialMap = {
|
||||
{0.09, Material{QColor(255,255,255),0,0.8}},
|
||||
{0.63, Material{QColor(165,176,207),0,0.8}},
|
||||
{1.00, Material{QColor(58,64,151),0,0.8}}
|
||||
};
|
||||
return { BaseStyle(std::make_shared<TransformStyle>(),
|
||||
std::make_shared<MaterialStyleStroke>(width, type, StrokeEndType::kFlat,
|
||||
std::make_shared<StrokeRadialGradient>(materialMap, false))) };
|
||||
}
|
||||
};
|
||||
vector<std::shared_ptr<ElementStyle>> style = {
|
||||
std::make_shared<StyleStrokeRadialGradient>(widths[0], StrokeType::kLeftSide),
|
||||
std::make_shared<StyleStrokeRadialGradient>(widths[1], StrokeType::kRightSide),
|
||||
std::make_shared<StyleStrokeRadialGradient>(widths[2], StrokeType::kLeftSide),
|
||||
};
|
||||
vector<std::shared_ptr<Element>> element = {
|
||||
std::make_shared<Element>(Element{ contours[0].first, style[0], contours[0].second}),
|
||||
std::make_shared<Element>(Element{ contours[1].first, style[1], contours[1].second}),
|
||||
std::make_shared<Element>(Element{ contours[2].first, style[2], contours[2].second}),
|
||||
};
|
||||
painting.addElement(*element[0], ElementTransform{ glm::vec2(-0.45,0.45), glm::vec2(0.25), 0, glm::bvec2(false), 0 });
|
||||
painting.addElement(*element[1], ElementTransform{ glm::vec2(-0.535,0.33), glm::vec2(0.15), 0, glm::bvec2(false), 0 });
|
||||
painting.addElement(*element[2], ElementTransform{ glm::vec2(-0.535,0.23), glm::vec2(0.15), 0, glm::bvec2(false), 0 });
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 1000; i++)
|
||||
|
|
|
@ -104,7 +104,11 @@ std::unique_ptr<MaterialStyle> Renderer::MaterialStyleStroke::clone() const
|
|||
|
||||
bool Renderer::MaterialStyleStroke::operator==(const MaterialStyle& m) const
|
||||
{
|
||||
return type() == m.type() && *materialStroke == *static_cast<const MaterialStyleStroke&>(m).materialStroke;
|
||||
return type() == m.type()
|
||||
&& halfWidth == static_cast<const MaterialStyleStroke&>(m).halfWidth
|
||||
&& strokeType == static_cast<const MaterialStyleStroke&>(m).strokeType
|
||||
&& endType == static_cast<const MaterialStyleStroke&>(m).endType
|
||||
&& *materialStroke == *static_cast<const MaterialStyleStroke&>(m).materialStroke;
|
||||
}
|
||||
|
||||
float Renderer::MaterialStyleStroke::getHalfWidth() const
|
||||
|
|
|
@ -54,7 +54,7 @@ namespace Renderer
|
|||
virtual std::unique_ptr<MaterialStyle> clone() const override;
|
||||
virtual bool operator==(const MaterialStyle&) const override;
|
||||
float getHalfWidth() const;
|
||||
//protected:
|
||||
|
||||
float halfWidth;
|
||||
StrokeType strokeType;
|
||||
StrokeEndType endType;
|
||||
|
|
|
@ -12,9 +12,11 @@ Renderer::RendererWidget::RendererWidget(QWidget* parent)
|
|||
auto openAction = new QAction(QStringLiteral("´ò¿ª"), menu);
|
||||
auto saveAction = new QAction(QStringLiteral("±£´æ"), menu);
|
||||
auto testAction = new QAction(QStringLiteral("²âÊÔ"), menu);
|
||||
auto test2Action = new QAction(QStringLiteral("²âÊÔ2"), menu);
|
||||
menu->addAction(openAction);
|
||||
menu->addAction(saveAction);
|
||||
menu->addAction(testAction);
|
||||
menu->addAction(test2Action);
|
||||
|
||||
ui.openButton->setHaloVisible(false);
|
||||
ui.openButton->setOverlayStyle(::Material::TintedOverlay);
|
||||
|
@ -47,7 +49,9 @@ Renderer::RendererWidget::RendererWidget(QWidget* parent)
|
|||
QObject::connect(testAction, &QAction::triggered, [&] {
|
||||
ui.openGLWidget->setModel("Models/Sponza/Sponza.gltf");
|
||||
});
|
||||
|
||||
QObject::connect(test2Action, &QAction::triggered, [&] {
|
||||
ui.openGLWidget->setModel("E:\\3D Objects\\Gate\\Gate.gltf");
|
||||
});
|
||||
ui.horizontalSlider->setValue(105);
|
||||
ui.horizontalSlider_2->setValue(80);
|
||||
ui.exposureSlider->setValue(60);
|
||||
|
|
|
@ -108,6 +108,27 @@ namespace UnitTest
|
|||
w.show();
|
||||
a.exec();
|
||||
}
|
||||
TEST_METHOD(TestRightSideFlat)
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
class StyleStrokeRadialGradient : public Renderer::ElementStyle
|
||||
{
|
||||
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override
|
||||
{
|
||||
std::map<float, Material> materialMap = {
|
||||
{0.20, Material{QColor(255,255,255)}},
|
||||
{0.60, Material{QColor(165,176,207)}},
|
||||
{1.00, Material{QColor(58,64,151)}}
|
||||
};
|
||||
return { BaseStyle(std::make_shared<TransformStyle>(),
|
||||
std::make_shared<MaterialStyleStroke>(200, StrokeType::kRightSide, StrokeEndType::kFlat,
|
||||
std::make_shared<StrokeRadialGradient>(materialMap, false))) };
|
||||
}
|
||||
} style;
|
||||
TestGLWidget w(style);
|
||||
w.show();
|
||||
a.exec();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CLASS(ElementRendererStokeMaterialTest)
|
||||
|
|
Loading…
Reference in New Issue