初步实现变宽样式
parent
edb529e7da
commit
5ac322fb30
|
@ -899,6 +899,36 @@ bool angleLargeThanPi(vec2 a, vec2 b)
|
||||||
|
|
||||||
/************************************************************************************/
|
/************************************************************************************/
|
||||||
|
|
||||||
|
float getLocalWidth(float t, vec2 lengthRate, float originWidth, uint widthMapSize, uint widthMapIndex)
|
||||||
|
{
|
||||||
|
if(widthMapSize == 0)
|
||||||
|
return originWidth;
|
||||||
|
float width;
|
||||||
|
vec2 lastData = unpackUnorm2x16(floatBitsToUint(style[widthMapIndex]));
|
||||||
|
float lastLevel = 0;
|
||||||
|
float lastWidth = lastData.y;
|
||||||
|
float currentLengthRate = mix(lengthRate.x, lengthRate.y, t);
|
||||||
|
bool found = false;
|
||||||
|
for (uint i = 0; i < widthMapSize; i++)
|
||||||
|
{
|
||||||
|
vec2 data = unpackUnorm2x16(floatBitsToUint(style[widthMapIndex + i]));
|
||||||
|
float level = data.x;
|
||||||
|
float currentWidth = data.y;
|
||||||
|
if (currentLengthRate <= level)
|
||||||
|
{
|
||||||
|
float a = (currentLengthRate - lastLevel) / (level - lastLevel);
|
||||||
|
width = mix(lastWidth, currentWidth, a);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lastWidth = currentWidth;
|
||||||
|
lastLevel = level;
|
||||||
|
}
|
||||||
|
if(!found)
|
||||||
|
width = lastWidth;
|
||||||
|
return width * originWidth;
|
||||||
|
}
|
||||||
|
|
||||||
void drawLine(in float d, uint styleHeadIndex, out vec4 elementColor, out vec2 metallicRoughness)
|
void drawLine(in float d, uint styleHeadIndex, out vec4 elementColor, out vec2 metallicRoughness)
|
||||||
{
|
{
|
||||||
elementColor = vec4(1);
|
elementColor = vec4(1);
|
||||||
|
@ -1100,6 +1130,7 @@ void main()
|
||||||
else // Stroke
|
else // Stroke
|
||||||
{
|
{
|
||||||
uint widthMapSize = floatBitsToUint(style[styleIndex + 1]);
|
uint widthMapSize = floatBitsToUint(style[styleIndex + 1]);
|
||||||
|
uint widthMapIndex = styleIndex + 2;
|
||||||
float minDistance = 1e38;
|
float minDistance = 1e38;
|
||||||
styleIndex += widthMapSize + 2;
|
styleIndex += widthMapSize + 2;
|
||||||
vec4 styleHead = unpackUnorm4x8(floatBitsToUint(style[styleIndex]));
|
vec4 styleHead = unpackUnorm4x8(floatBitsToUint(style[styleIndex]));
|
||||||
|
@ -1177,7 +1208,7 @@ void main()
|
||||||
|
|
||||||
float t;
|
float t;
|
||||||
float d = cubic_bezier_dis(localUV, p[0], p[1], p[2], p[3], true, t);
|
float d = cubic_bezier_dis(localUV, p[0], p[1], p[2], p[3], true, t);
|
||||||
float localWidth = strokeWidth; // * mix(lengthRate.x, lengthRate.y, t);
|
float localWidth = getLocalWidth(t, lengthRate, strokeWidth, widthMapSize, widthMapIndex);
|
||||||
if (d <= localWidth)
|
if (d <= localWidth)
|
||||||
{
|
{
|
||||||
bool hit = d < minDistance;
|
bool hit = d < minDistance;
|
||||||
|
|
|
@ -10,15 +10,55 @@
|
||||||
#include "../Painting/Element.h"
|
#include "../Painting/Element.h"
|
||||||
#include "../Painting/Painting.h"
|
#include "../Painting/Painting.h"
|
||||||
#include "../Painting/MaterialStyleStroke.h"
|
#include "../Painting/MaterialStyleStroke.h"
|
||||||
|
#include "../Painting/CubicBezier.h"
|
||||||
#include <util/PainterPathUtil.h>
|
#include <util/PainterPathUtil.h>
|
||||||
using namespace Renderer;
|
using namespace Renderer;
|
||||||
|
|
||||||
std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
|
std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
|
||||||
{
|
{
|
||||||
float lastLength = 0;
|
|
||||||
glm::vec2 lastPoint;
|
glm::vec2 lastPoint;
|
||||||
std::vector<glm::vec2> pathBuffer;
|
std::vector<std::vector<float>> lengths;
|
||||||
for (int i = 0; i < path.elementCount(); i++)
|
for (int i = 0; i < path.elementCount(); i++)
|
||||||
|
{
|
||||||
|
QPainterPath::Element element = path.elementAt(i);
|
||||||
|
switch (element.type)
|
||||||
|
{
|
||||||
|
case QPainterPath::MoveToElement:
|
||||||
|
{
|
||||||
|
lastPoint = glm::vec2(element.x, element.y);
|
||||||
|
lengths.push_back({ 0 });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QPainterPath::LineToElement:
|
||||||
|
{
|
||||||
|
glm::vec2 end = glm::vec2(element.x, element.y);
|
||||||
|
float length = glm::distance(lastPoint, end);
|
||||||
|
lengths.back().push_back(lengths.back().back() + length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QPainterPath::CurveToElement:
|
||||||
|
{
|
||||||
|
Point p1(element.x, element.y);
|
||||||
|
element = path.elementAt(++i);
|
||||||
|
Point p2(element.x, element.y);
|
||||||
|
element = path.elementAt(++i);
|
||||||
|
Point p3(element.x, element.y);
|
||||||
|
if (glm::vec2(p3.x, p3.y) != lastPoint)
|
||||||
|
{
|
||||||
|
float length = CubicBezier(std::vector{ Point(lastPoint.x, lastPoint.y), p1, p2, p3 }).getIntegralByT(1);
|
||||||
|
lengths.back().push_back(lengths.back().back() + length);
|
||||||
|
lastPoint = glm::vec2(p3.x, p3.y);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QPainterPath::CurveToDataElement:
|
||||||
|
qCritical() << "Read QPainterPath Error";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<glm::vec2> pathBuffer;
|
||||||
|
for (int i = 0, j = -1, k = 0; i < path.elementCount(); i++)
|
||||||
{
|
{
|
||||||
QPainterPath::Element element = path.elementAt(i);
|
QPainterPath::Element element = path.elementAt(i);
|
||||||
switch (element.type)
|
switch (element.type)
|
||||||
|
@ -28,8 +68,8 @@ std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
|
||||||
//qDebug() << element;
|
//qDebug() << element;
|
||||||
pathBuffer.emplace_back(std::numeric_limits<float>::infinity());
|
pathBuffer.emplace_back(std::numeric_limits<float>::infinity());
|
||||||
pathBuffer.emplace_back(element.x, element.y);
|
pathBuffer.emplace_back(element.x, element.y);
|
||||||
lastLength = 0;
|
|
||||||
lastPoint = glm::vec2(element.x, element.y);
|
lastPoint = glm::vec2(element.x, element.y);
|
||||||
|
j++;
|
||||||
break;
|
break;
|
||||||
case QPainterPath::LineToElement:
|
case QPainterPath::LineToElement:
|
||||||
{
|
{
|
||||||
|
@ -40,9 +80,9 @@ std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
|
||||||
pathBuffer.push_back(mid);
|
pathBuffer.push_back(mid);
|
||||||
pathBuffer.push_back(mid);
|
pathBuffer.push_back(mid);
|
||||||
pathBuffer.push_back(end);
|
pathBuffer.push_back(end);
|
||||||
float length = (i + 1.) / path.elementCount();
|
pathBuffer.emplace_back(lengths[j][k] / lengths[j].back(), lengths[j][k+1] / lengths[j].back());
|
||||||
pathBuffer.emplace_back(lastLength, length);
|
k++;
|
||||||
lastLength = length;
|
qDebug() << pathBuffer.back().x << pathBuffer.back().y;
|
||||||
lastPoint = end;
|
lastPoint = end;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -62,9 +102,9 @@ std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
|
||||||
pathBuffer.push_back(p1);
|
pathBuffer.push_back(p1);
|
||||||
pathBuffer.push_back(p2);
|
pathBuffer.push_back(p2);
|
||||||
pathBuffer.push_back(p3);
|
pathBuffer.push_back(p3);
|
||||||
float length = (i + 1.) / path.elementCount();
|
pathBuffer.emplace_back(lengths[j][k] / lengths[j].back(), lengths[j][k+1] / lengths[j].back());
|
||||||
pathBuffer.emplace_back(lastLength, length);
|
k++;
|
||||||
lastLength = length;
|
qDebug() << pathBuffer.back().x << pathBuffer.back().y;
|
||||||
lastPoint = p3;
|
lastPoint = p3;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -145,7 +185,7 @@ Renderer::ElementRenderer::ElementRenderer()
|
||||||
thread = std::jthread([&](std::stop_token stop) {
|
thread = std::jthread([&](std::stop_token stop) {
|
||||||
std::stop_callback cb(stop, [&] {
|
std::stop_callback cb(stop, [&] {
|
||||||
draw.notify_all();
|
draw.notify_all();
|
||||||
});
|
});
|
||||||
|
|
||||||
QOpenGLContext context;
|
QOpenGLContext context;
|
||||||
context.create();
|
context.create();
|
||||||
|
@ -205,7 +245,7 @@ Renderer::ElementRenderer::ElementRenderer()
|
||||||
draw.notify_all();
|
draw.notify_all();
|
||||||
}
|
}
|
||||||
context.doneCurrent();
|
context.doneCurrent();
|
||||||
});
|
});
|
||||||
|
|
||||||
while (!initialized)
|
while (!initialized)
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
|
|
|
@ -255,9 +255,12 @@ namespace UnitTest
|
||||||
}
|
}
|
||||||
TEST_METHOD(TestBothSidesGradientWidth)
|
TEST_METHOD(TestBothSidesGradientWidth)
|
||||||
{
|
{
|
||||||
QPainterPath testPath;
|
/*QPainterPath testPath;
|
||||||
testPath.moveTo(50, 50);
|
testPath.moveTo(50, 50);
|
||||||
testPath.cubicTo(50, 200, 200, 300, 300, 300);
|
testPath.cubicTo(50, 200, 200, 300, 300, 300);*/
|
||||||
|
QPainterPath testPath;
|
||||||
|
SvgFileLoader().loadSvgFile("../../svg/3.svg", testPath);
|
||||||
|
testPath = QTransform::fromScale(10, 10).map(testPath);
|
||||||
QApplication a(argc, argv);
|
QApplication a(argc, argv);
|
||||||
class StyleStrokeRadialGradient : public Renderer::ElementStyle
|
class StyleStrokeRadialGradient : public Renderer::ElementStyle
|
||||||
{
|
{
|
||||||
|
@ -269,8 +272,8 @@ namespace UnitTest
|
||||||
{1.00, Material{QColor(58,64,151)}}
|
{1.00, Material{QColor(58,64,151)}}
|
||||||
};
|
};
|
||||||
return { BaseStyle(std::make_shared<TransformStyle>(),
|
return { BaseStyle(std::make_shared<TransformStyle>(),
|
||||||
std::make_shared<MaterialStyleStroke>(20, StrokeType::kLeftSide, StrokeEndType::kRound,
|
std::make_shared<MaterialStyleStroke>(80, StrokeType::kRightSide, StrokeEndType::kFlatRound,
|
||||||
std::make_shared<StrokeRadialGradient>(materialMap, false))) };
|
std::make_shared<StrokeRadialGradient>(materialMap, false), std::map<float, float>{ {0,1},{1,0}})) };
|
||||||
}
|
}
|
||||||
} style;
|
} style;
|
||||||
TestGLWidget w(style, testPath);
|
TestGLWidget w(style, testPath);
|
||||||
|
|
Loading…
Reference in New Issue