Merge branch 'main' into dev-LayerStyle

dev-LayerStyle
ArgonarioD 2023-03-15 11:36:32 +08:00
commit 460428c135
7 changed files with 139 additions and 165 deletions

View File

@ -1150,11 +1150,6 @@ void main()
else else
tangentEnd = normalize(p[3] - p[1]); tangentEnd = normalize(p[3] - p[1]);
// if (onBegin ? shouldFillBeginCap(localUV, onVeryBegin, endType, p[0], tangentBegin,
// tangentEndLast)
// : (onEnd ? shouldFillEndCap(localUV, onVeryEnd, endType, p[3], tangentEnd,
// tangentBeginNext)
// : d < minDistance))
bool hit = d < minDistance; bool hit = d < minDistance;
if (onBegin) if (onBegin)
hit = hit && hit = hit &&

View File

@ -1023,14 +1023,14 @@ void drawLine(in float d, in uint styleIndex, out vec4 elementColor, out vec2 me
} }
} }
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; vec2 normal;
if (onVeryBegin) if (onVeryBegin)
{ {
if (endType == 0) if (endType % 2 == 0)
return true; return true;
else if (endType == 1) else if (endType % 2 == 1)
normal = normalize(mat2(0, 1, -1, 0) * (-tangentBegin)); normal = normalize(mat2(0, 1, -1, 0) * (-tangentBegin));
} }
else else
@ -1039,17 +1039,26 @@ bool shouldFillBeginCap(vec2 localUV, bool onVeryBegin, int endType, vec2 p3, ve
vec2 normalNow = normalize(mat2(0, 1, -1, 0) * (-tangentBegin)); vec2 normalNow = normalize(mat2(0, 1, -1, 0) * (-tangentBegin));
normal = normalLast + normalNow; 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; vec2 normal;
if (endType == 0) if (onVeryEnd)
return true; {
else if (endType == 1) if ((endType / 2) % 2 == 0)
normal = normalize(mat2(0, 1, -1, 0) * tangentEnd); return true;
return angleLargeThanPi(localUV - p0, normal); else if ((endType / 2) % 2 == 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);
} }
bool fillElement(vec2 localUV, uint contourIndex, uint linesOffset, uint pointsOffset, uint styleIndex, bool fillElement(vec2 localUV, uint contourIndex, uint linesOffset, uint pointsOffset, uint styleIndex,
@ -1100,8 +1109,8 @@ bool fillElement(vec2 localUV, uint contourIndex, uint linesOffset, uint pointsO
return hitElement; return hitElement;
} }
bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint pointsOffset, uint styleIndex, float widthHeightRatio, bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint pointsOffset, uint styleIndex,
inout vec4 elementColor, inout vec2 metallicRoughness) float widthHeightRatio, inout vec4 elementColor, inout vec2 metallicRoughness)
{ {
bool hitElement = false; bool hitElement = false;
float strokeWidth = elementData[styleIndex]; float strokeWidth = elementData[styleIndex];
@ -1135,12 +1144,44 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point
mat4x2 p = mat4x2 p =
mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]], elementData[pxIndex[1]], elementData[pyIndex[1]], mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]], elementData[pxIndex[1]], elementData[pyIndex[1]],
elementData[pxIndex[2]], elementData[pyIndex[2]], elementData[pxIndex[3]], elementData[pyIndex[3]]); elementData[pxIndex[2]], elementData[pyIndex[2]], elementData[pxIndex[3]], elementData[pyIndex[3]]);
p[0] *= ratio; p[0] *= ratio;
p[1] *= ratio; p[1] *= ratio;
p[2] *= ratio; p[2] *= ratio;
p[3] *= ratio; p[3] *= ratio;
vec2 tangentBeginNext;
if (contourIterator + 1 < contourIndex + 1 + lineCount)
{
uint lineIndex = elementIndexs[contourIterator + 1];
uint pLocation = linesOffset + 3 * lineIndex;
//vec2 percent = unpackUnorm2x16(elementIndexs[pLocation + 2]);
uvec4 pxIndex = uvec4(pointsOffset) +
2 * uvec4(elementIndexs[pLocation] >> 16, elementIndexs[pLocation] & 0xFFFF,
elementIndexs[pLocation + 1] >> 16, elementIndexs[pLocation + 1] & 0xFFFF);
uvec4 pyIndex = uvec4(1) + pxIndex;
mat4x2 pNext = mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]], elementData[pxIndex[1]],
elementData[pyIndex[1]], elementData[pxIndex[2]], elementData[pyIndex[2]],
elementData[pxIndex[3]], elementData[pyIndex[3]]);
pNext[0] *= ratio;
pNext[1] *= ratio;
pNext[2] *= ratio;
pNext[3] *= ratio;
if (pNext[0] == pNext[1] && pNext[2] == pNext[3])
{
pNext[1] = (pNext[0] + pNext[3]) / 2;
pNext[2] = pNext[1];
}
//if(pNext[0]!=p[3])
// break;
if (pNext[0] != pNext[1])
tangentBeginNext = normalize(pNext[0] - pNext[1]);
else
tangentBeginNext = normalize(pNext[0] - pNext[2]);
}
if (p[0] == p[1] && p[2] == p[3]) if (p[0] == p[1] && p[2] == p[3])
{ {
p[1] = (p[0] + p[3]) / 2; p[1] = (p[0] + p[3]) / 2;
@ -1158,7 +1199,10 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point
float d = cubic_bezier_dis(localUV, p[0], p[1], p[2], p[3], true); float d = cubic_bezier_dis(localUV, p[0], p[1], p[2], p[3], true);
if (d <= strokeWidth) if (d <= strokeWidth)
{ {
bool onBegin = distance(localUV, p[0]) <= strokeWidth && ( p3Last == p[0] || contourIterator==contourIndex + 1); bool onBegin =
distance(localUV, p[0]) <= strokeWidth; //&& (p3Last == p[0] || contourIterator == contourIndex + 1);
bool onEnd = distance(localUV, p[3]) <= strokeWidth;
vec2 tangentBegin; vec2 tangentBegin;
vec2 tangentEnd; vec2 tangentEnd;
if (p[0] != p[1]) if (p[0] != p[1])
@ -1170,30 +1214,36 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point
else else
tangentEnd = normalize(p[3] - p[1]); tangentEnd = normalize(p[3] - p[1]);
if (onBegin ? shouldFillBeginCap(localUV, percent[0]<1e-5, endType, p[0], tangentBegin, p3Last - p2Last) bool hit = d < minDistance;
: d < minDistance) if (onBegin)
hit =
hit && shouldFillBeginCap(localUV, percent[0] < 1e-5, endType, p[0], tangentBegin, p3Last - p2Last);
if (onEnd)
hit = hit &&
shouldFillEndCap(localUV, percent[1] > 1 - 1e-5, endType, p[3], tangentEnd, tangentBeginNext);
if (hit)
{ {
minDistance = min(minDistance, d);
bool reverse = p[3].y - p[0].y < 0.; bool reverse = p[3].y - p[0].y < 0.;
if (tangentBegin.y == 0.) // if (tangentBegin.y == 0.)
tangentBegin.y = reverse ? eps : -eps; // tangentBegin.y = reverse ? eps : -eps;
if (tangentEnd.y == 0.) // if (tangentEnd.y == 0.)
tangentEnd.y = reverse ? -eps : eps; // tangentEnd.y = reverse ? -eps : eps;
int intTest = cubic_bezier_int_test2(localUV, p[0], p[1], p[2], p[3], reverse) + int intTest = cubic_bezier_int_test2(localUV, p[0], p[1], p[2], p[3], reverse) +
ray_int_test(localUV, p[0], tangentBegin, reverse) + ray_int_test(localUV, p[0], tangentBegin, reverse) +
ray_int_test(localUV, p[3], tangentEnd, reverse); ray_int_test(localUV, p[3], tangentEnd, reverse);
if (lineType == 2 || (intTest % 2 == int(lineType))) if (lineType == 2 || (intTest % 2 == int(lineType)))
{ {
minDistance = min(minDistance, d);
hitElement = true; hitElement = true;
// elementColor = vec4(1, 1, 0, 1); // elementColor = vec4(1, 1, 0, 1);
vec2 metallicRoughness; vec2 metallicRoughness;
drawLine(minDistance / strokeWidth, styleIndex, elementColor, metallicRoughness); drawLine(minDistance / strokeWidth, styleIndex, elementColor, metallicRoughness);
} }
else if (p3Last == p[0]) // else if (p3Last == p[0])
hitElement = false; // hitElement = false;
} }
tangentEndLast = tangentEnd; tangentEndLast = tangentEnd;
} }
@ -1202,7 +1252,7 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point
} }
if (hitElement && distance(localUV, p3Last) <= strokeWidth) if (hitElement && distance(localUV, p3Last) <= strokeWidth)
{ {
hitElement = shouldFillEndCap(localUV, endType, p3Last, tangentEndLast); // hitElement = shouldFillEndCap(localUV, percent[1] > 1 - 1e-5, endType, p3Last, tangentEndLast, vec2(0));
} }
// if (minDistance <= 0.001) // if (minDistance <= 0.001)
@ -1261,8 +1311,8 @@ bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, ou
} }
else // Ïß else // Ïß
{ {
hitElement = strokeElement(localUV, contourIndex, linesOffset, pointsOffset, styleIndex, widthHeightRatio, hitElement = strokeElement(localUV, contourIndex, linesOffset, pointsOffset, styleIndex,
elementColor, metallicRoughness); widthHeightRatio, elementColor, metallicRoughness);
} }
elementBvhIndex = elementBvhLength; elementBvhIndex = elementBvhLength;
@ -1303,7 +1353,7 @@ void main()
vec3 debugBVH = vec3(0); vec3 debugBVH = vec3(0);
// bool debugHit = false; // bool debugHit = false;
vec4 color = vec4(0.76, 0.33, 0.15, -1); vec4 color = vec4(0.76, 0.33, 0.15, -1);
//vec4 color = vec4(1,1,1, -1); // vec4 color = vec4(1,1,1, -1);
vec2 metallicRoughness = vec2(0, 0.8); vec2 metallicRoughness = vec2(0, 0.8);
stack.top = 0; stack.top = 0;
uint index = 0, visitTime = 0; uint index = 0, visitTime = 0;
@ -1373,7 +1423,7 @@ void main()
imageStore(gBaseColor, pixelLocation, vec4(color.rgb, 1)); imageStore(gBaseColor, pixelLocation, vec4(color.rgb, 1));
imageStore(gMetallicRoughness, pixelLocation, vec4(metallicRoughness, 0, 1)); imageStore(gMetallicRoughness, pixelLocation, vec4(metallicRoughness, 0, 1));
return; //return;
if (/*color.a!=-1&&*/ debugBVH == vec3(0)) if (/*color.a!=-1&&*/ debugBVH == vec3(0))
{ {
// imageStore(gBaseColor, pixelLocation, vec4(vec3(1, 1, 0),1)); // imageStore(gBaseColor, pixelLocation, vec4(vec3(1, 1, 0),1));

View File

@ -8,6 +8,9 @@ using Renderer::Element;
using Renderer::ElementTransform; using Renderer::ElementTransform;
using glm::bvec2; using glm::bvec2;
using std::max; using std::max;
using std::min;
const double PaintingUtil::pi = acos(-1);
QJsonObject PaintingUtil::readJsonFile(QString jsonFilePath) { QJsonObject PaintingUtil::readJsonFile(QString jsonFilePath) {
QFile jsonFile(jsonFilePath); QFile jsonFile(jsonFilePath);
@ -27,74 +30,69 @@ Painting PaintingUtil::transfromToPainting(QString jsonFilePath) {
ElementManager *elementManager = new ElementManager(jsonObj, Renderer::ElementRenderer::instance()); ElementManager *elementManager = new ElementManager(jsonObj, Renderer::ElementRenderer::instance());
LayerManager* layerManager = new LayerManager(jsonObj, elementManager); LayerManager* layerManager = new LayerManager(jsonObj, elementManager);
traverseLayTree(layerManager->getRoot(), transform, flip, painting); traverseLayTree(layerManager->getRoot(), transform, flip, painting);
// FIXME: 为了编译通过添加的返回
return painting; return painting;
} }
void PaintingUtil::traverseLayTree(LayerWrapper* nowLayer, QTransform transform, bvec2 flip, Painting& painting) { void PaintingUtil::traverseLayTree(LayerWrapper* nowLayer, QTransform transform, bvec2 flip, Painting& painting) {
LeafLayerWrapper* leafLayer = dynamic_cast<LeafLayerWrapper*>(nowLayer); LeafLayerWrapper* leafLayer = dynamic_cast<LeafLayerWrapper*>(nowLayer);
PixelPath pixelPath = nowLayer->getCache(); PixelPath pixelPath = nowLayer->getCache();
double centerX = pixelPath.getBoundingRect().center().x(); QPainterPath painterPath = pixelPath.getPainterPath();
double centerY = pixelPath.getBoundingRect().center().y(); QRectF bound = painterPath.boundingRect();
flip ^= bvec2(nowLayer->property.flipHorizontally, nowLayer->property.flipVertically); flip ^= bvec2(nowLayer->property.flipHorizontally, nowLayer->property.flipVertically);
QRectF transBound = transform.map(pixelPath.getPainterPath()).boundingRect(); transform = nowLayer->property.transform * transform;
transform.translate(nowLayer->property.offset.x(), nowLayer->property.offset.y())
.translate(-centerX, -centerY)
.rotate(nowLayer->property.rotation)
.scale(nowLayer->property.scale.x(), nowLayer->property.scale.y())
.translate(centerX, centerY);
if (leafLayer != nullptr) { if (leafLayer != nullptr) {
Element element; Element element;
ElementTransform elementTrans; ElementTransform elementTrans;
QRectF bound = pixelPath.getBoundingRect();
element.ratio = bound.width() / bound.height(); element.ratio = bound.width() / bound.height();
// transform to initial painterPath // transform to initial painterPath
QTransform trans;
trans.translate(-centerX, -centerY)
.scale(1 / nowLayer->property.scale.x(), 1 / nowLayer->property.scale.y())
.rotate(-nowLayer->property.rotation)
.translate(centerX, centerY)
.translate(-nowLayer->property.offset.x(), -nowLayer->property.offset.y());
QPainterPath painterPath = trans.map(pixelPath.getPainterPath());
// transfrom to -1£¬ 1 // transfrom to -1£¬ 1
bound = painterPath.boundingRect(); QTransform trans;
trans.reset(); trans.scale(1 / bound.width(), 1 / bound.height());
trans.translate(1, 1); trans.translate(-bound.center().x(), -bound.center().y());
trans.scale(2 / bound.width(), 2 / bound.height());
trans.translate(bound.x(), bound.y());
painterPath = trans.map(painterPath);
element.contour.reset(new vector<vector<Renderer::Point> >(PainterPathUtil::transformToLines(painterPath))); element.contour.reset(new vector<vector<Renderer::Point> >(PainterPathUtil::transformToLines(trans.map(painterPath))));
QSize screenSize = pixelPath.getPixmap().size(); QSize screenSize = pixelPath.getPixmap().size();
//element.style.reset(new Renderer::ElementStyleStrokeDemo(0.06));
painterPath = transform.map(painterPath);
bound = painterPath.boundingRect();
elementTrans.center = glm::vec2( elementTrans.center = glm::vec2(
(2 * (transBound.x() + transBound.width()) - screenSize.width()) / screenSize.width(), (bound.center().x() - screenSize.width()) / screenSize.width(),
(2 * (transBound.y() + transBound.height()) - screenSize.height()) / screenSize.height() (bound.center().y() - screenSize.height()) / screenSize.height()
); );
decomposeTransform(transform, elementTrans.rotation, elementTrans.scale); decomposeTransform(transform, elementTrans.rotation, elementTrans.scale);
elementTrans.flip = glm::bvec2( elementTrans.flip = glm::bvec2(
nowLayer->property.flipHorizontally, nowLayer->property.flipHorizontally,
nowLayer->property.flipVertically nowLayer->property.flipVertically
); );
painting.addElement(element, elementTrans);
return; return;
} }
FolderLayerWrapper* folderLayer = dynamic_cast<FolderLayerWrapper*>(nowLayer); FolderLayerWrapper* folderLayer = dynamic_cast<FolderLayerWrapper*>(nowLayer);
for (auto sonLayer : folderLayer->children) { if (folderLayer != nullptr) {
traverseLayTree(sonLayer.get(), transform, flip, painting); for (auto sonLayer : folderLayer->children) {
traverseLayTree(sonLayer.get(), transform, flip, painting);
}
} }
return; return;
} }
void PaintingUtil::decomposeTransform(QTransform trans, float& angle, glm::vec2& scale) { void PaintingUtil::decomposeTransform(QTransform trans, float& angle, glm::vec2& scale) {
trans.translate(-trans.dx(), -trans.dy()); qDebug() << trans;
trans.setMatrix(
trans.m11(), trans.m12(), trans.m13(),
trans.m21(), trans.m22(), trans.m23(),
0, 0, 1);
//qDebug() << trans.dx() << trans.dy();
int count = 0; int count = 0;
double norm = 0, n = 0; double norm = 0, n = 0;
QTransform R = trans, Rit, Rnext; QTransform R = trans, Rit, Rnext;
do { do {
++count; ++count;
Rit = R.inverted(); Rit = R.transposed().inverted();
Rnext.setMatrix( Rnext.setMatrix(
(R.m11() + Rit.m11()) / 2, (R.m11() + Rit.m11()) / 2,
(R.m12() + Rit.m12()) / 2, (R.m12() + Rit.m12()) / 2,
@ -121,7 +119,13 @@ void PaintingUtil::decomposeTransform(QTransform trans, float& angle, glm::vec2&
+ fabs(R.m33() - Rnext.m33())); + fabs(R.m33() - Rnext.m33()));
R = Rnext; R = Rnext;
} while (count < 100 && norm > 0.0001); } while (count < 100 && norm > 0.0001);
angle = acos(R.m11()); double cosValue = max(-1.0, min(R.m11(), 1.0));
double sinValue = max(-1.0, min(R.m12(), 1.0));
angle = acos(cosValue) * 180 / pi;
if (sinValue < 0) {
angle = 360 - angle;
}
qDebug() << angle;
R = R.inverted() * trans; R = R.inverted() * trans;
scale = glm::vec2(R.m11(), R.m22()); scale = glm::vec2(R.m11(), R.m22());
return; return;

View File

@ -5,11 +5,12 @@
class PaintingUtil class PaintingUtil
{ {
private: private:
static const double pi;
static QJsonObject readJsonFile(QString jsonFilePath); static QJsonObject readJsonFile(QString jsonFilePath);
static void traverseLayTree(LayerWrapper* nowLayer, QTransform transform, glm::bvec2 flip, Renderer::Painting& painting); static void traverseLayTree(LayerWrapper* nowLayer, QTransform transform, glm::bvec2 flip, Renderer::Painting& painting);
static void decomposeTransform(QTransform trans, float& angle, glm::vec2& scale);
public: public:
static Renderer::Painting transfromToPainting(QString jsonFilePath); static Renderer::Painting transfromToPainting(QString jsonFilePath);
static void decomposeTransform(QTransform trans, float& angle, glm::vec2& scale);
}; };

View File

@ -14,6 +14,7 @@
#include "../Editor/util/PainterPathUtil.h" #include "../Editor/util/PainterPathUtil.h"
#include "../Editor/util/SvgFileLoader.h" #include "../Editor/util/SvgFileLoader.h"
#include <ThirdPartyLib/qquick/qquicksvgparser_p.h> #include <ThirdPartyLib/qquick/qquicksvgparser_p.h>
#include <util/PaintingUtil.h>
#include "Painting/MaterialStyleStroke.h" #include "Painting/MaterialStyleStroke.h"
using namespace Renderer; using namespace Renderer;
@ -228,104 +229,7 @@ GLuint Renderer::Model::loadPainting(std::string path)
if (iter != paintingLoaded.end()) if (iter != paintingLoaded.end())
return iter->second; return iter->second;
//vector<std::shared_ptr<Contour>> contour = { Painting painting = PaintingUtil::transfromToPainting("D:\\BigC\\Project\\ArchitectureColoredPainting\\data.json");
// std::make_shared<Contour>(SvgParser("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z", 100, 100).parse()),
// std::make_shared<Contour>(SvgParser("M308.49,212.25l23,28.38-82,78.31c-14.28,13.64-26.34-20.6-53.44,9.32l-30.24-13.4,63.56-51.59L190.71,215.6l-32.92,26.72L149.5,232.1l32.92-26.72L173.2,194l-32.91,26.72-7.38-9.08L165.83,185l-38.69-47.66L94.22,164,85,152.65l32.91-26.72-9.21-11.35L75.79,141.3l-5.53-6.81,32.92-26.72L94,96.42,61.05,123.14l-12-14.76L37.72,117.6l12,14.75L30.41,148,0,110.55,136.2,0l30.4,37.46L147.31,53.12l-12-14.76L124,47.58l12,14.75L103.05,89.05l9.21,11.35,32.92-26.72,5.52,6.81-32.91,26.72L127,118.56l32.92-26.72,9.21,11.35-32.91,26.72,38.69,47.67,32.91-26.72,7.37,9.08-32.91,26.72L191.49,198l32.92-26.72,8.29,10.22-32.92,26.71,38.7,47.68L302,204.3l6.45,7.95Z", 331.52, 328.26).parse()),
// std::make_shared<Contour>(SvgParser("M377,459.61a11.26,11.26,0,0,1,11.27-11.27H696.12a11.27,11.27,0,0,0,11-8.62A359.84,359.84,0,0,0,708,280.56a11.26,11.26,0,0,0-11-8.73H388.27A11.26,11.26,0,0,1,377,260.57h0a11.26,11.26,0,0,1,11.27-11.26H683.71A11.32,11.32,0,0,0,694.28,234C649.8,113.69,542.57,23.85,412.3,4.12a11.22,11.22,0,0,0-12.76,11.17v158.9a11.26,11.26,0,0,0,11.26,11.27H583.12a11.32,11.32,0,0,0,9.26-17.75c-31.67-46.59-78.51-75.2-109.11-90.07a11.25,11.25,0,0,0-16.13,10.17V115.2a11.24,11.24,0,0,0,6.22,10.07l7.51,3.76a11.28,11.28,0,0,1,5,15.12h0a11.27,11.27,0,0,1-15.11,5l-20-10a11.27,11.27,0,0,1-6.22-10.07V54a11.27,11.27,0,0,1,14.62-10.75c5.11,1.59,125.66,40.35,172.24,149A11.27,11.27,0,0,1,621.11,208H388.27A11.26,11.26,0,0,1,377,196.73V11.36A11.32,11.32,0,0,0,365.89.08C363.34,0,360.79,0,358.22,0s-5.11,0-7.66.08a11.32,11.32,0,0,0-11.11,11.28V196.74A11.26,11.26,0,0,1,328.18,208H95.35A11.27,11.27,0,0,1,85,192.3c46.57-108.67,167.12-147.42,172.23-149A11.26,11.26,0,0,1,271.86,54v75.11a11.25,11.25,0,0,1-6.23,10.07l-20,10a11.27,11.27,0,0,1-15.11-5h0a11.26,11.26,0,0,1,5-15.11l7.52-3.76a11.27,11.27,0,0,0,6.22-10.07V87.82a11.25,11.25,0,0,0-16.14-10.16c-30.6,14.87-77.45,43.48-109.1,90.07a11.3,11.3,0,0,0,9.25,17.74H305.66a11.26,11.26,0,0,0,11.27-11.26V15.31A11.22,11.22,0,0,0,304.17,4.14C173.88,23.86,66.66,113.71,22.17,234a11.32,11.32,0,0,0,10.56,15.29H328.18a11.26,11.26,0,0,1,11.27,11.26v0a11.26,11.26,0,0,1-11.27,11.26H19.52a11.26,11.26,0,0,0-11,8.72,359.84,359.84,0,0,0,.83,159.16,11.26,11.26,0,0,0,11,8.61H328.18a11.26,11.26,0,0,1,11.27,11.27h0a11.26,11.26,0,0,1-11.27,11.26h-294a11.32,11.32,0,0,0-10.53,15.4C69,604.65,175.3,692.78,304.16,712.3a11.21,11.21,0,0,0,12.76-11.16V542.22A11.26,11.26,0,0,0,305.66,531h-166c-9.53,0-14.89,11.22-8.69,18.47,34.09,39.77,74.45,65.66,101.77,80.18a11.25,11.25,0,0,0,16.53-10V591a11.26,11.26,0,0,1,11.26-11.26h0A11.26,11.26,0,0,1,271.85,591v63.85A11.27,11.27,0,0,1,256.8,665.5c-4.45-1.59-109.58-40-171-139.9a11.27,11.27,0,0,1,9.59-17.17H328.18a11.26,11.26,0,0,1,11.27,11.26V705.08a11.32,11.32,0,0,0,11.11,11.28q3.82.07,7.66.08c2.57,0,5.12,0,7.67-.08A11.32,11.32,0,0,0,377,705.08V519.69a11.25,11.25,0,0,1,11.27-11.26H621.1a11.26,11.26,0,0,1,9.59,17.16c-61.46,99.87-166.59,138.3-171,139.9a11.27,11.27,0,0,1-15-10.61V591a11.26,11.26,0,0,1,11.26-11.26h0A11.26,11.26,0,0,1,467.14,591v28.6a11.25,11.25,0,0,0,16.53,10c27.33-14.53,67.68-40.42,101.77-80.19,6.2-7.23.85-18.46-8.69-18.46h-166a11.26,11.26,0,0,0-11.26,11.26V701.12a11.21,11.21,0,0,0,12.76,11.17c128.86-19.51,235.14-107.66,280.48-226a11.33,11.33,0,0,0-10.53-15.41h-294A11.25,11.25,0,0,1,377,459.61ZM35.27,399.53V316.9a11.26,11.26,0,0,1,11.27-11.26H669.92a11.25,11.25,0,0,1,11.26,11.26v82.63a11.25,11.25,0,0,1-11.26,11.26H46.54a11.27,11.27,0,0,1-11.27-11.26Z", 716.45, 716.44).parse())
//};
vector<std::pair<std::shared_ptr<Contour>, float>> contours;
QPainterPath painterPaths[3];
QQuickSvgParser::parsePathDataFast("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z",
painterPaths[0]);
if (!SvgFileLoader().loadSvgFile("../svg/2.svg", painterPaths[1]))
qCritical() << "load error";
/*QQuickSvgParser::parsePathDataFast("M292.82,107.78s0,0,0,0,0,3.59,0,7.62c0,3.85,0,5.78.06,6.43a19.94,19.94,0,0,0,2.87,7.58,15.85,15.85,0,0,0,6.61,6.23A14.75,14.75,0,0,0,310,137a11.69,11.69,0,0,0,7.59-2.92,11,11,0,0,0,3.2-6.84c.15-1.27.58-4.84-1.79-7.64a8.54,8.54,0,0,0-3.56-2.44c-1.32-.52-3.32-1.31-5.06-.33a5.41,5.41,0,0,0-2.14,3,3.48,3.48,0,0,0-.16,2.71c.78,1.86,3.36,2.14,3.47,2.15",
painterPaths[1]);*/
QQuickSvgParser::parsePathDataFast("M377,459.61a11.26,11.26,0,0,1,11.27-11.27H696.12a11.27,11.27,0,0,0,11-8.62A359.84,359.84,0,0,0,708,280.56a11.26,11.26,0,0,0-11-8.73H388.27A11.26,11.26,0,0,1,377,260.57h0a11.26,11.26,0,0,1,11.27-11.26H683.71A11.32,11.32,0,0,0,694.28,234C649.8,113.69,542.57,23.85,412.3,4.12a11.22,11.22,0,0,0-12.76,11.17v158.9a11.26,11.26,0,0,0,11.26,11.27H583.12a11.32,11.32,0,0,0,9.26-17.75c-31.67-46.59-78.51-75.2-109.11-90.07a11.25,11.25,0,0,0-16.13,10.17V115.2a11.24,11.24,0,0,0,6.22,10.07l7.51,3.76a11.28,11.28,0,0,1,5,15.12h0a11.27,11.27,0,0,1-15.11,5l-20-10a11.27,11.27,0,0,1-6.22-10.07V54a11.27,11.27,0,0,1,14.62-10.75c5.11,1.59,125.66,40.35,172.24,149A11.27,11.27,0,0,1,621.11,208H388.27A11.26,11.26,0,0,1,377,196.73V11.36A11.32,11.32,0,0,0,365.89.08C363.34,0,360.79,0,358.22,0s-5.11,0-7.66.08a11.32,11.32,0,0,0-11.11,11.28V196.74A11.26,11.26,0,0,1,328.18,208H95.35A11.27,11.27,0,0,1,85,192.3c46.57-108.67,167.12-147.42,172.23-149A11.26,11.26,0,0,1,271.86,54v75.11a11.25,11.25,0,0,1-6.23,10.07l-20,10a11.27,11.27,0,0,1-15.11-5h0a11.26,11.26,0,0,1,5-15.11l7.52-3.76a11.27,11.27,0,0,0,6.22-10.07V87.82a11.25,11.25,0,0,0-16.14-10.16c-30.6,14.87-77.45,43.48-109.1,90.07a11.3,11.3,0,0,0,9.25,17.74H305.66a11.26,11.26,0,0,0,11.27-11.26V15.31A11.22,11.22,0,0,0,304.17,4.14C173.88,23.86,66.66,113.71,22.17,234a11.32,11.32,0,0,0,10.56,15.29H328.18a11.26,11.26,0,0,1,11.27,11.26v0a11.26,11.26,0,0,1-11.27,11.26H19.52a11.26,11.26,0,0,0-11,8.72,359.84,359.84,0,0,0,.83,159.16,11.26,11.26,0,0,0,11,8.61H328.18a11.26,11.26,0,0,1,11.27,11.27h0a11.26,11.26,0,0,1-11.27,11.26h-294a11.32,11.32,0,0,0-10.53,15.4C69,604.65,175.3,692.78,304.16,712.3a11.21,11.21,0,0,0,12.76-11.16V542.22A11.26,11.26,0,0,0,305.66,531h-166c-9.53,0-14.89,11.22-8.69,18.47,34.09,39.77,74.45,65.66,101.77,80.18a11.25,11.25,0,0,0,16.53-10V591a11.26,11.26,0,0,1,11.26-11.26h0A11.26,11.26,0,0,1,271.85,591v63.85A11.27,11.27,0,0,1,256.8,665.5c-4.45-1.59-109.58-40-171-139.9a11.27,11.27,0,0,1,9.59-17.17H328.18a11.26,11.26,0,0,1,11.27,11.26V705.08a11.32,11.32,0,0,0,11.11,11.28q3.82.07,7.66.08c2.57,0,5.12,0,7.67-.08A11.32,11.32,0,0,0,377,705.08V519.69a11.25,11.25,0,0,1,11.27-11.26H621.1a11.26,11.26,0,0,1,9.59,17.16c-61.46,99.87-166.59,138.3-171,139.9a11.27,11.27,0,0,1-15-10.61V591a11.26,11.26,0,0,1,11.26-11.26h0A11.26,11.26,0,0,1,467.14,591v28.6a11.25,11.25,0,0,0,16.53,10c27.33-14.53,67.68-40.42,101.77-80.19,6.2-7.23.85-18.46-8.69-18.46h-166a11.26,11.26,0,0,0-11.26,11.26V701.12a11.21,11.21,0,0,0,12.76,11.17c128.86-19.51,235.14-107.66,280.48-226a11.33,11.33,0,0,0-10.53-15.41h-294A11.25,11.25,0,0,1,377,459.61ZM35.27,399.53V316.9a11.26,11.26,0,0,1,11.27-11.26H669.92a11.25,11.25,0,0,1,11.26,11.26v82.63a11.25,11.25,0,0,1-11.26,11.26H46.54a11.27,11.27,0,0,1-11.27-11.26Z",
painterPaths[2]);
for (auto& i : painterPaths)
{
auto [contour, ratio] = PainterPathUtil::toNormalizedLines(i);
contours.emplace_back(std::make_shared<Contour>(contour), ratio);
}
vector<std::shared_ptr<ElementStyle>> style = {
std::make_shared<ElementStyleFillDemo>(),
std::make_shared<ElementStyleStrokeDemo>(0.02),
std::make_shared<ElementStyleStrokeRadialGradientDemo>(0.2)
};
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[2], contours[1].second}),
std::make_shared<Element>(Element{ contours[2].first, style[0], contours[2].second}),
};
Painting painting;
if (path == "0.json")
{
painting.addElement(*element[0], ElementTransform{ glm::vec2(-0.45,-0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 });
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++)
{
float x = (float)rand() / RAND_MAX * 2 - 1;
float y = (float)rand() / RAND_MAX * 2 - 1;
painting.addElement(*element[i % 3], ElementTransform{ glm::vec2(x,y), glm::vec2(0.025), (float)rand() / RAND_MAX * 360, glm::bvec2(false), 0 });
}
}
painting.generateBuffers(glFunc); painting.generateBuffers(glFunc);

View File

@ -141,12 +141,13 @@ bool LineTree::handleShortCutNode(LineTreeNode& fa, LineTreeNode& nowTreeNode, d
nowTreeNode.lineSet.push_back(lineIndex); nowTreeNode.lineSet.push_back(lineIndex);
} }
} }
if (nowTreeNode.lineSet.size() <= requiredLineMin) { if (nowTreeNode.lineSet.size() <= requiredLineMin
|| (nowTreeNode.bound.z()-nowTreeNode.bound.x())*sqrt(2) <= lineWidth) {
if (nowTreeNode.lineSet.empty()) if (nowTreeNode.lineSet.empty())
return false; return false;
restOfTreeNodes.push_back(nowTreeNode); restOfTreeNodes.push_back(nowTreeNode);
nowTreeNode.divided = false; nowTreeNode.divided = false;
v.push_back(nowTreeNode); //v.push_back(nowTreeNode);
return false; return false;
} }
else { else {

View File

@ -7,6 +7,7 @@
#include "Renderer/Painting/CubicBezier.h" #include "Renderer/Painting/CubicBezier.h"
#include <Renderer/Painting/StraightLine.h> #include <Renderer/Painting/StraightLine.h>
#include <ElementPoolWidget.h> #include <ElementPoolWidget.h>
#include <util/PaintingUtil.h>
using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace Microsoft::VisualStudio::CppUnitTestFramework;
@ -119,4 +120,22 @@ namespace UnitTest
a.exec(); a.exec();
} }
}; };
TEST_CLASS(PaintingUtilTest)
{
TEST_METHOD(TransfromTest)
{
qInstallMessageHandler(messageHandler);
QPainterPath path;
path.addRect(0, 0, 20, 20);
QTransform trans;
qDebug() << path.boundingRect();
//qDebug() << trans;
//qDebug() << acos(-0.707107);
glm::vec2 scale;
float rotate;
PaintingUtil::decomposeTransform(trans, rotate, scale);
qDebug() << rotate;
qDebug() << scale.x << scale.y;
}
};
} }