Compare commits
4 Commits
e97e6d5281
...
6191eb919e
Author | SHA1 | Date |
---|---|---|
ArgonarioD | 6191eb919e | |
ArgonarioD | 0ff779c5b2 | |
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;
|
vec2 normal;
|
||||||
if (onVeryBegin)
|
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));
|
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 (onVeryEnd)
|
||||||
|
{
|
||||||
if (endType == 0)
|
if (endType == 0)
|
||||||
return true;
|
return true;
|
||||||
else if (endType == 1)
|
else if (endType == 1)
|
||||||
normal = normalize(mat2(0, 1, -1, 0) * tangentEnd);
|
normal = normalize(mat2(0, 1, -1, 0) * tangentEnd);
|
||||||
return angleLargeThanPi(localUV - p0, normal);
|
}
|
||||||
|
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()
|
void main()
|
||||||
|
@ -1058,9 +1067,13 @@ void main()
|
||||||
// endType = 1;
|
// endType = 1;
|
||||||
int debugBegin = 0;
|
int debugBegin = 0;
|
||||||
bool onVeryBegin = false;
|
bool onVeryBegin = false;
|
||||||
|
bool onVeryEnd = false;
|
||||||
vec2 tangentEndLast;
|
vec2 tangentEndLast;
|
||||||
|
uint lastHitIndex = 0;
|
||||||
|
bool lastHitElement = false;
|
||||||
|
hitElement = false;
|
||||||
for (uint pathIndex = 0; pathIndex < pathSize; pathIndex++)
|
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];
|
vec2 pTemp = path[pathIndex];
|
||||||
if (isinf(pTemp.x))
|
if (isinf(pTemp.x))
|
||||||
|
@ -1068,7 +1081,7 @@ void main()
|
||||||
// TODO: ¼ì²âÊÇ·ñ·â±Õ²¢´¦Àí
|
// TODO: ¼ì²âÊÇ·ñ·â±Õ²¢´¦Àí
|
||||||
if (hitElement && distance(localUV, p3Last) <= strokeWidth)
|
if (hitElement && distance(localUV, p3Last) <= strokeWidth)
|
||||||
{
|
{
|
||||||
hitElement = shouldFillEndCap(localUV, endType, p3Last, tangentEndLast);
|
// hitElement = shouldFillEndCap(localUV, true, endType, p3Last, tangentEndLast);
|
||||||
}
|
}
|
||||||
|
|
||||||
pBegin = path[++pathIndex];
|
pBegin = path[++pathIndex];
|
||||||
|
@ -1079,10 +1092,30 @@ void main()
|
||||||
}
|
}
|
||||||
mat4x2 p = mat4x2(p3Last, pTemp, path[++pathIndex], path[++pathIndex]);
|
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);
|
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];
|
bool onBegin = distance(localUV, p[0]) <= strokeWidth;
|
||||||
|
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])
|
||||||
|
@ -1094,11 +1127,19 @@ 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, p3Last - p2Last)
|
// if (onBegin ? shouldFillBeginCap(localUV, onVeryBegin, endType, p[0], tangentBegin,
|
||||||
: d < minDistance)
|
// 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.;
|
bool reverse = p[3].y - p[0].y < 0.;
|
||||||
|
|
||||||
if (tangentBegin.y == 0.)
|
if (tangentBegin.y == 0.)
|
||||||
|
@ -1111,13 +1152,26 @@ void main()
|
||||||
|
|
||||||
if (lineType == 2 || (intTest % 2 == int(lineType)))
|
if (lineType == 2 || (intTest % 2 == int(lineType)))
|
||||||
{
|
{
|
||||||
|
minDistance = min(minDistance, d);
|
||||||
|
lastHitElement = hitElement;
|
||||||
|
lastHitIndex = pathIndex;
|
||||||
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 (lastHitIndex == pathIndex - 3)
|
||||||
hitElement = false;
|
// {
|
||||||
|
// hitElement = lastHitElement;
|
||||||
|
// lastHitElement = false;
|
||||||
|
// // if(lastHitElement ==false)
|
||||||
|
// //{
|
||||||
|
// // hitElement = true;
|
||||||
|
// // elementColor = vec4(1, 1, 0, 1);
|
||||||
|
// //}
|
||||||
|
|
||||||
|
// minDistance = 1e38;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
tangentEndLast = tangentEnd;
|
tangentEndLast = tangentEnd;
|
||||||
}
|
}
|
||||||
|
@ -1127,7 +1181,7 @@ void main()
|
||||||
}
|
}
|
||||||
if (hitElement && distance(localUV, p3Last) <= strokeWidth)
|
if (hitElement && distance(localUV, p3Last) <= strokeWidth)
|
||||||
{
|
{
|
||||||
hitElement = shouldFillEndCap(localUV, endType, p3Last, tangentEndLast);
|
// hitElement = shouldFillEndCap(localUV, true, endType, p3Last, tangentEndLast);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hitElement)
|
if (hitElement)
|
||||||
|
|
|
@ -37,7 +37,6 @@ layout(std430, binding = 4) buffer elementDataBuffer
|
||||||
|
|
||||||
const float PI = 3.14159265358979;
|
const float PI = 3.14159265358979;
|
||||||
|
|
||||||
|
|
||||||
const uint STACK_SIZE = 10;
|
const uint STACK_SIZE = 10;
|
||||||
|
|
||||||
struct Stack
|
struct Stack
|
||||||
|
@ -77,7 +76,6 @@ struct Stack
|
||||||
}
|
}
|
||||||
} stack, elementStack;
|
} stack, elementStack;
|
||||||
|
|
||||||
|
|
||||||
// Modified from http://tog.acm.org/resources/GraphicsGems/gems/Roots3And4.c
|
// Modified from http://tog.acm.org/resources/GraphicsGems/gems/Roots3And4.c
|
||||||
// Credits to Doublefresh for hinting there
|
// Credits to Doublefresh for hinting there
|
||||||
int solve_quadric(vec2 coeffs, inout vec2 roots)
|
int solve_quadric(vec2 coeffs, inout vec2 roots)
|
||||||
|
@ -151,7 +149,6 @@ int solve_cubic(vec3 coeffs, inout vec3 r)
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int segment_int_test(vec2 uv, vec2 p0, vec2 p1)
|
int segment_int_test(vec2 uv, vec2 p0, vec2 p1)
|
||||||
{
|
{
|
||||||
p0 -= uv;
|
p0 -= uv;
|
||||||
|
@ -299,15 +296,19 @@ bvec3 cubic_bezier_sign_test(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3)
|
||||||
|
|
||||||
// int n_ints = 0;
|
// int n_ints = 0;
|
||||||
bvec3 result = bvec3(false);
|
bvec3 result = bvec3(false);
|
||||||
for(int i=0;i<3;i++){
|
for (int i = 0; i < 3; i++)
|
||||||
if(i < n_roots){
|
{
|
||||||
if(roots[i] >= 0. && roots[i] <= 1.){
|
if (i < n_roots)
|
||||||
|
{
|
||||||
|
if (roots[i] >= 0. && roots[i] <= 1.)
|
||||||
|
{
|
||||||
float x_pos = -p0.x + 3. * p1.x - 3. * p2.x + p3.x;
|
float x_pos = -p0.x + 3. * p1.x - 3. * p2.x + p3.x;
|
||||||
x_pos = x_pos * roots[i] + 3. * p0.x - 6. * p1.x + 3. * p2.x;
|
x_pos = x_pos * roots[i] + 3. * p0.x - 6. * p1.x + 3. * p2.x;
|
||||||
x_pos = x_pos * roots[i] + -3. * p0.x + 3. * p1.x;
|
x_pos = x_pos * roots[i] + -3. * p0.x + 3. * p1.x;
|
||||||
x_pos = x_pos * roots[i] + p0.x;
|
x_pos = x_pos * roots[i] + p0.x;
|
||||||
|
|
||||||
if(x_pos > uv.x){
|
if (x_pos > uv.x)
|
||||||
|
{
|
||||||
result[1] = !result[1];
|
result[1] = !result[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -320,24 +321,32 @@ bvec3 cubic_bezier_sign_test(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3)
|
||||||
vec2 nor1 = vec2(tang1.y, -tang1.x);
|
vec2 nor1 = vec2(tang1.y, -tang1.x);
|
||||||
vec2 nor2 = vec2(tang2.y, -tang2.x);
|
vec2 nor2 = vec2(tang2.y, -tang2.x);
|
||||||
|
|
||||||
if(p0.y < p1.y){
|
if (p0.y < p1.y)
|
||||||
if((uv.y<=p0.y) && (dot(uv-p0.xy,nor1)>0.)){
|
{
|
||||||
|
if ((uv.y <= p0.y) && (dot(uv - p0.xy, nor1) > 0.))
|
||||||
|
{
|
||||||
result[0] = !result[0];
|
result[0] = !result[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else
|
||||||
if(!(uv.y<=p0.y) && !(dot(uv-p0.xy,nor1)>0.)){
|
{
|
||||||
|
if (!(uv.y <= p0.y) && !(dot(uv - p0.xy, nor1) > 0.))
|
||||||
|
{
|
||||||
result[0] = !result[0];
|
result[0] = !result[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(p2.y<p3.y){
|
if (p2.y < p3.y)
|
||||||
if(!(uv.y<=p3.y) && dot(uv-p3.xy,nor2)>0.){
|
{
|
||||||
|
if (!(uv.y <= p3.y) && dot(uv - p3.xy, nor2) > 0.)
|
||||||
|
{
|
||||||
result[2] = !result[2];
|
result[2] = !result[2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else
|
||||||
if((uv.y<=p3.y) && !(dot(uv-p3.xy,nor2)>0.)){
|
{
|
||||||
|
if ((uv.y <= p3.y) && !(dot(uv - p3.xy, nor2) > 0.))
|
||||||
|
{
|
||||||
result[2] = !result[2];
|
result[2] = !result[2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -355,7 +364,8 @@ const float eps = .000005;
|
||||||
const int halley_iterations = 8;
|
const int halley_iterations = 8;
|
||||||
// lagrange positive real root upper bound
|
// lagrange positive real root upper bound
|
||||||
// see for example: https://doi.org/10.1016/j.jsc.2014.09.038
|
// see for example: https://doi.org/10.1016/j.jsc.2014.09.038
|
||||||
float upper_bound_lagrange5(float a0, float a1, float a2, float a3, float a4){
|
float upper_bound_lagrange5(float a0, float a1, float a2, float a3, float a4)
|
||||||
|
{
|
||||||
|
|
||||||
vec4 coeffs1 = vec4(a0, a1, a2, a3);
|
vec4 coeffs1 = vec4(a0, a1, a2, a3);
|
||||||
|
|
||||||
|
@ -383,7 +393,8 @@ float upper_bound_lagrange5(float a0, float a1, float a2, float a3, float a4){
|
||||||
}
|
}
|
||||||
|
|
||||||
// lagrange upper bound applied to f(-x) to get lower bound
|
// lagrange upper bound applied to f(-x) to get lower bound
|
||||||
float lower_bound_lagrange5(float a0, float a1, float a2, float a3, float a4){
|
float lower_bound_lagrange5(float a0, float a1, float a2, float a3, float a4)
|
||||||
|
{
|
||||||
|
|
||||||
vec4 coeffs1 = vec4(-a0, a1, -a2, a3);
|
vec4 coeffs1 = vec4(-a0, a1, -a2, a3);
|
||||||
|
|
||||||
|
@ -410,7 +421,8 @@ float lower_bound_lagrange5(float a0, float a1, float a2, float a3, float a4){
|
||||||
return -max_max - max_max2;
|
return -max_max - max_max2;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 parametric_cub_bezier(float t, vec2 p0, vec2 p1, vec2 p2, vec2 p3){
|
vec2 parametric_cub_bezier(float t, vec2 p0, vec2 p1, vec2 p2, vec2 p3)
|
||||||
|
{
|
||||||
vec2 a0 = (-p0 + 3. * p1 - 3. * p2 + p3);
|
vec2 a0 = (-p0 + 3. * p1 - 3. * p2 + p3);
|
||||||
vec2 a1 = (3. * p0 - 6. * p1 + 3. * p2);
|
vec2 a1 = (3. * p0 - 6. * p1 + 3. * p2);
|
||||||
vec2 a2 = (-3. * p0 + 3. * p1);
|
vec2 a2 = (-3. * p0 + 3. * p1);
|
||||||
|
@ -419,7 +431,8 @@ vec2 parametric_cub_bezier(float t, vec2 p0, vec2 p1, vec2 p2, vec2 p3){
|
||||||
return (((a0 * t) + a1) * t + a2) * t + a3;
|
return (((a0 * t) + a1) * t + a2) * t + a3;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sort_roots3(inout vec3 roots){
|
void sort_roots3(inout vec3 roots)
|
||||||
|
{
|
||||||
vec3 tmp;
|
vec3 tmp;
|
||||||
|
|
||||||
tmp[0] = min(roots[0], min(roots[1], roots[2]));
|
tmp[0] = min(roots[0], min(roots[1], roots[2]));
|
||||||
|
@ -429,7 +442,8 @@ void sort_roots3(inout vec3 roots){
|
||||||
roots = tmp;
|
roots = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sort_roots4(inout vec4 roots){
|
void sort_roots4(inout vec4 roots)
|
||||||
|
{
|
||||||
vec4 tmp;
|
vec4 tmp;
|
||||||
|
|
||||||
vec2 min1_2 = min(roots.xz, roots.yw);
|
vec2 min1_2 = min(roots.xz, roots.yw);
|
||||||
|
@ -446,7 +460,8 @@ void sort_roots4(inout vec4 roots){
|
||||||
roots = tmp;
|
roots = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
float eval_poly5(float a0, float a1, float a2, float a3, float a4, float x){
|
float eval_poly5(float a0, float a1, float a2, float a3, float a4, float x)
|
||||||
|
{
|
||||||
|
|
||||||
float f = ((((x + a4) * x + a3) * x + a2) * x + a1) * x + a0;
|
float f = ((((x + a4) * x + a3) * x + a2) * x + a1) * x + a0;
|
||||||
|
|
||||||
|
@ -457,7 +472,8 @@ float eval_poly5(float a0, float a1, float a2, float a3, float a4, float x){
|
||||||
// basically a variant of newton raphson which converges quicker and has bigger basins of convergence
|
// basically a variant of newton raphson which converges quicker and has bigger basins of convergence
|
||||||
// see http://mathworld.wolfram.com/HalleysMethod.html
|
// see http://mathworld.wolfram.com/HalleysMethod.html
|
||||||
// or https://en.wikipedia.org/wiki/Halley%27s_method
|
// or https://en.wikipedia.org/wiki/Halley%27s_method
|
||||||
float halley_iteration5(float a0, float a1, float a2, float a3, float a4, float x){
|
float halley_iteration5(float a0, float a1, float a2, float a3, float a4, float x)
|
||||||
|
{
|
||||||
|
|
||||||
float f = ((((x + a4) * x + a3) * x + a2) * x + a1) * x + a0;
|
float f = ((((x + a4) * x + a3) * x + a2) * x + a1) * x + a0;
|
||||||
float f1 = (((5. * x + 4. * a4) * x + 3. * a3) * x + 2. * a2) * x + a1;
|
float f1 = (((5. * x + 4. * a4) * x + 3. * a3) * x + 2. * a2) * x + a1;
|
||||||
|
@ -466,7 +482,8 @@ float halley_iteration5(float a0, float a1, float a2, float a3, float a4, float
|
||||||
return x - (2. * f * f1) / (2. * f1 * f1 - f * f2);
|
return x - (2. * f * f1) / (2. * f1 * f1 - f * f2);
|
||||||
}
|
}
|
||||||
|
|
||||||
float halley_iteration4(vec4 coeffs, float x){
|
float halley_iteration4(vec4 coeffs, float x)
|
||||||
|
{
|
||||||
|
|
||||||
float f = (((x + coeffs[3]) * x + coeffs[2]) * x + coeffs[1]) * x + coeffs[0];
|
float f = (((x + coeffs[3]) * x + coeffs[2]) * x + coeffs[1]) * x + coeffs[0];
|
||||||
float f1 = ((4. * x + 3. * coeffs[3]) * x + 2. * coeffs[2]) * x + coeffs[1];
|
float f1 = ((4. * x + 3. * coeffs[3]) * x + 2. * coeffs[2]) * x + coeffs[1];
|
||||||
|
@ -477,7 +494,8 @@ float halley_iteration4(vec4 coeffs, float x){
|
||||||
|
|
||||||
// Modified from http://tog.acm.org/resources/GraphicsGems/gems/Roots3And4.c
|
// Modified from http://tog.acm.org/resources/GraphicsGems/gems/Roots3And4.c
|
||||||
// Credits to Doublefresh for hinting there
|
// Credits to Doublefresh for hinting there
|
||||||
int solve_quartic(vec4 coeffs, inout vec4 s){
|
int solve_quartic(vec4 coeffs, inout vec4 s)
|
||||||
|
{
|
||||||
|
|
||||||
float a = coeffs[3];
|
float a = coeffs[3];
|
||||||
float b = coeffs[2];
|
float b = coeffs[2];
|
||||||
|
@ -529,17 +547,21 @@ int solve_quartic(vec4 coeffs, inout vec4 s){
|
||||||
float u = z * z - r;
|
float u = z * z - r;
|
||||||
float v = 2. * z - p;
|
float v = 2. * z - p;
|
||||||
|
|
||||||
if(u > -eps){
|
if (u > -eps)
|
||||||
|
{
|
||||||
u = sqrt(abs(u));
|
u = sqrt(abs(u));
|
||||||
}
|
}
|
||||||
else{
|
else
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(v > -eps){
|
if (v > -eps)
|
||||||
|
{
|
||||||
v = sqrt(abs(v));
|
v = sqrt(abs(v));
|
||||||
}
|
}
|
||||||
else{
|
else
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,12 +579,15 @@ int solve_quartic(vec4 coeffs, inout vec4 s){
|
||||||
int old_num = num;
|
int old_num = num;
|
||||||
|
|
||||||
num += solve_quadric(quad_coeffs, tmp);
|
num += solve_quadric(quad_coeffs, tmp);
|
||||||
if(old_num!=num){
|
if (old_num != num)
|
||||||
if(old_num == 0){
|
{
|
||||||
|
if (old_num == 0)
|
||||||
|
{
|
||||||
s[0] = tmp[0];
|
s[0] = tmp[0];
|
||||||
s[1] = tmp[1];
|
s[1] = tmp[1];
|
||||||
}
|
}
|
||||||
else{//old_num == 2
|
else
|
||||||
|
{ // old_num == 2
|
||||||
s[2] = tmp[0];
|
s[2] = tmp[0];
|
||||||
s[3] = tmp[1];
|
s[3] = tmp[1];
|
||||||
}
|
}
|
||||||
|
@ -574,8 +599,10 @@ int solve_quartic(vec4 coeffs, inout vec4 s){
|
||||||
float sub = 1. / 4. * a;
|
float sub = 1. / 4. * a;
|
||||||
|
|
||||||
/* single halley iteration to fix cancellation */
|
/* single halley iteration to fix cancellation */
|
||||||
for(int i=0;i<4;i+=2){
|
for (int i = 0; i < 4; i += 2)
|
||||||
if(i < num){
|
{
|
||||||
|
if (i < num)
|
||||||
|
{
|
||||||
s[i] -= sub;
|
s[i] -= sub;
|
||||||
s[i] = halley_iteration4(coeffs, s[i]);
|
s[i] = halley_iteration4(coeffs, s[i]);
|
||||||
|
|
||||||
|
@ -586,7 +613,8 @@ int solve_quartic(vec4 coeffs, inout vec4 s){
|
||||||
|
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
float cubic_bezier_dis(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3, bool roundEnd){
|
float cubic_bezier_dis(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3, bool roundEnd)
|
||||||
|
{
|
||||||
|
|
||||||
// switch points when near to end point to minimize numerical error
|
// switch points when near to end point to minimize numerical error
|
||||||
// only needed when control point(s) very far away
|
// only needed when control point(s) very far away
|
||||||
|
@ -659,57 +687,71 @@ float cubic_bezier_dis(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3, bool roundEn
|
||||||
|
|
||||||
// compute root isolating intervals by roots of derivative and outer root bounds
|
// compute root isolating intervals by roots of derivative and outer root bounds
|
||||||
// only roots going form - to + considered, because only those result in a minimum
|
// only roots going form - to + considered, because only those result in a minimum
|
||||||
if(num_roots_drv==4){
|
if (num_roots_drv == 4)
|
||||||
if(eval_poly5(b0,b1,b2,b3,b4,roots_drv[0]) > 0.){
|
{
|
||||||
|
if (eval_poly5(b0, b1, b2, b3, b4, roots_drv[0]) > 0.)
|
||||||
|
{
|
||||||
a[0] = lb;
|
a[0] = lb;
|
||||||
b[0] = roots_drv[0];
|
b[0] = roots_drv[0];
|
||||||
num_roots = 1;
|
num_roots = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sign(eval_poly5(b0,b1,b2,b3,b4,roots_drv[1])) != sign(eval_poly5(b0,b1,b2,b3,b4,roots_drv[2]))){
|
if (sign(eval_poly5(b0, b1, b2, b3, b4, roots_drv[1])) != sign(eval_poly5(b0, b1, b2, b3, b4, roots_drv[2])))
|
||||||
if(num_roots == 0){
|
{
|
||||||
|
if (num_roots == 0)
|
||||||
|
{
|
||||||
a[0] = roots_drv[1];
|
a[0] = roots_drv[1];
|
||||||
b[0] = roots_drv[2];
|
b[0] = roots_drv[2];
|
||||||
num_roots = 1;
|
num_roots = 1;
|
||||||
}
|
}
|
||||||
else{
|
else
|
||||||
|
{
|
||||||
a[1] = roots_drv[1];
|
a[1] = roots_drv[1];
|
||||||
b[1] = roots_drv[2];
|
b[1] = roots_drv[2];
|
||||||
num_roots = 2;
|
num_roots = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(eval_poly5(b0,b1,b2,b3,b4,roots_drv[3]) < 0.){
|
if (eval_poly5(b0, b1, b2, b3, b4, roots_drv[3]) < 0.)
|
||||||
if(num_roots == 0){
|
{
|
||||||
|
if (num_roots == 0)
|
||||||
|
{
|
||||||
a[0] = roots_drv[3];
|
a[0] = roots_drv[3];
|
||||||
b[0] = ub;
|
b[0] = ub;
|
||||||
num_roots = 1;
|
num_roots = 1;
|
||||||
}
|
}
|
||||||
else if(num_roots == 1){
|
else if (num_roots == 1)
|
||||||
|
{
|
||||||
a[1] = roots_drv[3];
|
a[1] = roots_drv[3];
|
||||||
b[1] = ub;
|
b[1] = ub;
|
||||||
num_roots = 2;
|
num_roots = 2;
|
||||||
}
|
}
|
||||||
else{
|
else
|
||||||
|
{
|
||||||
a[2] = roots_drv[3];
|
a[2] = roots_drv[3];
|
||||||
b[2] = ub;
|
b[2] = ub;
|
||||||
num_roots = 3;
|
num_roots = 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else
|
||||||
if(num_roots_drv==2){
|
{
|
||||||
if(eval_poly5(b0,b1,b2,b3,b4,roots_drv[0]) < 0.){
|
if (num_roots_drv == 2)
|
||||||
|
{
|
||||||
|
if (eval_poly5(b0, b1, b2, b3, b4, roots_drv[0]) < 0.)
|
||||||
|
{
|
||||||
num_roots = 1;
|
num_roots = 1;
|
||||||
a[0] = roots_drv[1];
|
a[0] = roots_drv[1];
|
||||||
b[0] = ub;
|
b[0] = ub;
|
||||||
}
|
}
|
||||||
else if(eval_poly5(b0,b1,b2,b3,b4,roots_drv[1]) > 0.){
|
else if (eval_poly5(b0, b1, b2, b3, b4, roots_drv[1]) > 0.)
|
||||||
|
{
|
||||||
num_roots = 1;
|
num_roots = 1;
|
||||||
a[0] = lb;
|
a[0] = lb;
|
||||||
b[0] = roots_drv[0];
|
b[0] = roots_drv[0];
|
||||||
}
|
}
|
||||||
else{
|
else
|
||||||
|
{
|
||||||
num_roots = 2;
|
num_roots = 2;
|
||||||
|
|
||||||
a[0] = lb;
|
a[0] = lb;
|
||||||
|
@ -718,9 +760,9 @@ float cubic_bezier_dis(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3, bool roundEn
|
||||||
a[1] = roots_drv[1];
|
a[1] = roots_drv[1];
|
||||||
b[1] = ub;
|
b[1] = ub;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else{//num_roots_drv==0
|
else
|
||||||
|
{ // num_roots_drv==0
|
||||||
vec3 roots_snd_drv = vec3(1e38);
|
vec3 roots_snd_drv = vec3(1e38);
|
||||||
int num_roots_snd_drv = solve_cubic(c2, roots_snd_drv);
|
int num_roots_snd_drv = solve_cubic(c2, roots_snd_drv);
|
||||||
|
|
||||||
|
@ -741,31 +783,44 @@ float cubic_bezier_dis(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3, bool roundEn
|
||||||
int num_roots_trd_drv = 0;
|
int num_roots_trd_drv = 0;
|
||||||
vec2 roots_trd_drv = vec2(1e38);
|
vec2 roots_trd_drv = vec2(1e38);
|
||||||
|
|
||||||
if(num_roots_snd_drv!=3){
|
if (num_roots_snd_drv != 3)
|
||||||
|
{
|
||||||
num_roots_trd_drv = solve_quadric(c3, roots_trd_drv);
|
num_roots_trd_drv = solve_quadric(c3, roots_trd_drv);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0;i<3;i++){
|
for (int i = 0; i < 3; i++)
|
||||||
if(i < num_roots){
|
{
|
||||||
for(int j=0;j<3;j+=2){
|
if (i < num_roots)
|
||||||
if(j < num_roots_snd_drv){
|
{
|
||||||
if(a[i] < roots_snd_drv[j] && b[i] > roots_snd_drv[j]){
|
for (int j = 0; j < 3; j += 2)
|
||||||
if(eval_poly5(b0,b1,b2,b3,b4,roots_snd_drv[j]) > 0.){
|
{
|
||||||
|
if (j < num_roots_snd_drv)
|
||||||
|
{
|
||||||
|
if (a[i] < roots_snd_drv[j] && b[i] > roots_snd_drv[j])
|
||||||
|
{
|
||||||
|
if (eval_poly5(b0, b1, b2, b3, b4, roots_snd_drv[j]) > 0.)
|
||||||
|
{
|
||||||
b[i] = roots_snd_drv[j];
|
b[i] = roots_snd_drv[j];
|
||||||
}
|
}
|
||||||
else{
|
else
|
||||||
|
{
|
||||||
a[i] = roots_snd_drv[j];
|
a[i] = roots_snd_drv[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(int j=0;j<2;j++){
|
for (int j = 0; j < 2; j++)
|
||||||
if(j < num_roots_trd_drv){
|
{
|
||||||
if(a[i] < roots_trd_drv[j] && b[i] > roots_trd_drv[j]){
|
if (j < num_roots_trd_drv)
|
||||||
if(eval_poly5(b0,b1,b2,b3,b4,roots_trd_drv[j]) > 0.){
|
{
|
||||||
|
if (a[i] < roots_trd_drv[j] && b[i] > roots_trd_drv[j])
|
||||||
|
{
|
||||||
|
if (eval_poly5(b0, b1, b2, b3, b4, roots_trd_drv[j]) > 0.)
|
||||||
|
{
|
||||||
b[i] = roots_trd_drv[j];
|
b[i] = roots_trd_drv[j];
|
||||||
}
|
}
|
||||||
else{
|
else
|
||||||
|
{
|
||||||
a[i] = roots_trd_drv[j];
|
a[i] = roots_trd_drv[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -779,15 +834,17 @@ float cubic_bezier_dis(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3, bool roundEn
|
||||||
|
|
||||||
// compute roots with halley's method
|
// compute roots with halley's method
|
||||||
|
|
||||||
for(int i=0;i<3;i++){
|
for (int i = 0; i < 3; i++)
|
||||||
if(i < num_roots){
|
{
|
||||||
|
if (i < num_roots)
|
||||||
|
{
|
||||||
roots[i] = .5 * (a[i] + b[i]);
|
roots[i] = .5 * (a[i] + b[i]);
|
||||||
|
|
||||||
for(int j=0;j<halley_iterations;j++){
|
for (int j = 0; j < halley_iterations; j++)
|
||||||
|
{
|
||||||
roots[i] = halley_iteration5(b0, b1, b2, b3, b4, roots[i]);
|
roots[i] = halley_iteration5(b0, b1, b2, b3, b4, roots[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// compute squared distance to nearest point on curve
|
// compute squared distance to nearest point on curve
|
||||||
if (roundEnd)
|
if (roundEnd)
|
||||||
{
|
{
|
||||||
|
@ -797,21 +854,20 @@ float cubic_bezier_dis(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3, bool roundEn
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(roots[i]<0.||roots[i]>1.) d0=min(d0,1e38);
|
if (roots[i] < 0. || roots[i] > 1.)
|
||||||
|
d0 = min(d0, 1e38);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
vec2 to_curve = uv - parametric_cub_bezier(roots[i], p0, p1, p2, p3);
|
vec2 to_curve = uv - parametric_cub_bezier(roots[i], p0, p1, p2, p3);
|
||||||
d0 = min(d0, dot(to_curve, to_curve));
|
d0 = min(d0, dot(to_curve, to_curve));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sqrt(d0);
|
return sqrt(d0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int cubic_bezier_int_test2(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3, bool reverse)
|
int cubic_bezier_int_test2(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3, bool reverse)
|
||||||
{
|
{
|
||||||
float cu = (-p0.y + 3. * p1.y - 3. * p2.y + p3.y);
|
float cu = (-p0.y + 3. * p1.y - 3. * p2.y + p3.y);
|
||||||
|
@ -831,8 +887,10 @@ int cubic_bezier_int_test2(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3, bool rev
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (abs(cu) < .0001) n_roots = solve_quadric(vec2(co / qu, li / qu), roots.xy);
|
if (abs(cu) < .0001)
|
||||||
else n_roots = solve_cubic(vec3(co / cu, li / cu, qu / cu), roots);
|
n_roots = solve_quadric(vec2(co / qu, li / qu), roots.xy);
|
||||||
|
else
|
||||||
|
n_roots = solve_cubic(vec3(co / cu, li / cu, qu / cu), roots);
|
||||||
|
|
||||||
for (int i = 0; i < n_roots; i++)
|
for (int i = 0; i < n_roots; i++)
|
||||||
{
|
{
|
||||||
|
@ -843,7 +901,8 @@ int cubic_bezier_int_test2(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3, bool rev
|
||||||
x_pos = x_pos * roots[i] + -3. * p0.x + 3. * p1.x;
|
x_pos = x_pos * roots[i] + -3. * p0.x + 3. * p1.x;
|
||||||
x_pos = x_pos * roots[i] + p0.x;
|
x_pos = x_pos * roots[i] + p0.x;
|
||||||
|
|
||||||
if (reverse? x_pos < uv.x: x_pos > uv.x) n_ints++;
|
if (reverse ? x_pos < uv.x : x_pos > uv.x)
|
||||||
|
n_ints++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -858,10 +917,12 @@ int ray_int_test(vec2 uv, vec2 p0, vec2 direction, bool reverse)
|
||||||
vec2 nor = -direction;
|
vec2 nor = -direction;
|
||||||
nor = vec2(nor.y, -nor.x);
|
nor = vec2(nor.y, -nor.x);
|
||||||
float sgn = p0.y > direction.y ? 1. : -1.;
|
float sgn = p0.y > direction.y ? 1. : -1.;
|
||||||
if(reverse) sgn = -sgn;
|
if (reverse)
|
||||||
|
sgn = -sgn;
|
||||||
return dot(nor, p0) * sgn < 0. ? 0 : 1;
|
return dot(nor, p0) * sgn < 0. ? 0 : 1;
|
||||||
}
|
}
|
||||||
else return 0;
|
else
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 bezierTangent(float t, vec2 p0, vec2 p1, vec2 p2, vec2 p3)
|
vec2 bezierTangent(float t, vec2 p0, vec2 p1, vec2 p2, vec2 p3)
|
||||||
|
@ -962,65 +1023,54 @@ void drawLine(in float d, in uint styleIndex, out vec4 elementColor, out vec2 me
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, out vec2 metallicRoughness, inout vec3 debugBVH = vec3(0))
|
bool shouldFillBeginCap(vec2 localUV, bool onVeryBegin, int endType, vec2 p3, vec2 tangentBegin, vec2 tangentEndLast)
|
||||||
|
{
|
||||||
|
vec2 normal;
|
||||||
|
if (onVeryBegin)
|
||||||
|
{
|
||||||
|
if (endType == 0)
|
||||||
|
return true;
|
||||||
|
else if (endType == 1)
|
||||||
|
normal = normalize(mat2(0, 1, -1, 0) * (-tangentBegin));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vec2 normalLast = normalize(mat2(0, 1, -1, 0) * tangentEndLast);
|
||||||
|
vec2 normalNow = normalize(mat2(0, 1, -1, 0) * (-tangentBegin));
|
||||||
|
normal = normalLast + normalNow;
|
||||||
|
}
|
||||||
|
return angleLargeThanPi(normal, localUV - p3);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool shouldFillEndCap(vec2 localUV, int endType, vec2 p0, vec2 tangentEnd)
|
||||||
|
{
|
||||||
|
vec2 normal;
|
||||||
|
if (endType == 0)
|
||||||
|
return true;
|
||||||
|
else if (endType == 1)
|
||||||
|
normal = normalize(mat2(0, 1, -1, 0) * tangentEnd);
|
||||||
|
return angleLargeThanPi(localUV - p0, normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fillElement(vec2 localUV, uint contourIndex, uint linesOffset, uint pointsOffset, uint styleIndex,
|
||||||
|
inout vec4 elementColor, inout vec2 metallicRoughness)
|
||||||
{
|
{
|
||||||
bool hitElement = false;
|
bool hitElement = false;
|
||||||
vec4 elementColor = vec4(-1);
|
|
||||||
metallicRoughness = vec2(0, 0.8);
|
|
||||||
|
|
||||||
uint currentOffset[] = elementOffset[elementIndex];
|
|
||||||
uint elementBvhRoot = currentOffset[0];
|
|
||||||
uint styleIndex = currentOffset[1];
|
|
||||||
uint elementBvhLength = 0x80000000;
|
|
||||||
uint pointsOffset = currentOffset[2];
|
|
||||||
uint linesOffset = currentOffset[3];
|
|
||||||
|
|
||||||
elementStack.top = 0;
|
|
||||||
uint elementBvhIndex = 0;
|
|
||||||
while (elementBvhIndex < elementBvhLength || !elementStack.empty())
|
|
||||||
{
|
|
||||||
|
|
||||||
while (elementBvhIndex < elementBvhLength)
|
|
||||||
{
|
|
||||||
vec4 bound = bvhBound[elementBvhRoot + elementBvhIndex];
|
|
||||||
uint leftChild = bvhChildren[elementBvhRoot + elementBvhIndex].x;
|
|
||||||
|
|
||||||
if (all(lessThan(bound.xy, localUV)) && all(lessThan(localUV, bound.zw)))
|
|
||||||
{
|
|
||||||
if (leftChild >= elementBvhLength)
|
|
||||||
{
|
|
||||||
if (any(greaterThan(bound.xy+vec2(0.003), localUV)) || any(greaterThan(localUV, bound.zw-vec2(0.003))))
|
|
||||||
{
|
|
||||||
debugBVH.g = 0;
|
|
||||||
debugBVH.r += 1;
|
|
||||||
}
|
|
||||||
//uint styleIndex = bvhChildren[elementBvhRoot + elementBvhIndex].y;
|
|
||||||
//uint elementType = bvhChildren[elementBvhRoot + elementBvhIndex].y;
|
|
||||||
//float elementType = elementData[styleIndex];
|
|
||||||
bool isFillStyle = elementData[styleIndex]<=0;
|
|
||||||
// for(int i = 0; i<200;i++)
|
|
||||||
if (isFillStyle) //Ãæ
|
|
||||||
{
|
|
||||||
uint contourIndex = linesOffset + leftChild - 0x80000000;
|
|
||||||
|
|
||||||
uint num_its = 0;
|
uint num_its = 0;
|
||||||
|
|
||||||
uint lineCount = elementIndexs[contourIndex];
|
uint lineCount = elementIndexs[contourIndex];
|
||||||
|
|
||||||
for (uint contourIterator = contourIndex + 1; contourIterator < contourIndex + 1 + lineCount; contourIterator++)
|
for (uint contourIterator = contourIndex + 1; contourIterator < contourIndex + 1 + lineCount; contourIterator++)
|
||||||
{
|
{
|
||||||
uint lineIndex = elementIndexs[contourIterator];
|
uint lineIndex = elementIndexs[contourIterator];
|
||||||
uint pLocation = linesOffset + 2 * lineIndex;
|
uint pLocation = linesOffset + 2 * lineIndex;
|
||||||
uvec4 pxIndex = uvec4(pointsOffset)+2*uvec4(elementIndexs[pLocation]>>16, elementIndexs[pLocation]&0xFFFF, elementIndexs[pLocation+1]>>16, elementIndexs[pLocation+1]&0xFFFF);
|
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;
|
uvec4 pyIndex = uvec4(1) + pxIndex;
|
||||||
mat4x2 p = mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]],
|
mat4x2 p =
|
||||||
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[2]], elementData[pyIndex[2]], elementData[pxIndex[3]], elementData[pyIndex[3]]);
|
||||||
elementData[pxIndex[3]], elementData[pyIndex[3]]);
|
|
||||||
// vec2 p[4] = {vec2(elementData[pxIndex[0]], elementData[pyIndex[0]]),
|
|
||||||
// vec2(elementData[pxIndex[1]], elementData[pyIndex[1]]),
|
|
||||||
// vec2(elementData[pxIndex[2]],elementData[pyIndex[2]]),
|
|
||||||
// vec2(elementData[pxIndex[3]], elementData[pyIndex[3]])};
|
|
||||||
// if (bound.z == p[0].x && distance(localUV, p[3]) < 0.01)
|
// if (bound.z == p[0].x && distance(localUV, p[3]) < 0.01)
|
||||||
// {
|
// {
|
||||||
// debugBVH = vec3(0, 0, 1);
|
// debugBVH = vec3(0, 0, 1);
|
||||||
|
@ -1031,7 +1081,6 @@ bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, ou
|
||||||
// {
|
// {
|
||||||
// num_its += segment_int_test(localUV, p0, p3);
|
// num_its += segment_int_test(localUV, p0, p3);
|
||||||
// }
|
// }
|
||||||
//
|
|
||||||
// else
|
// else
|
||||||
num_its += cubic_bezier_int_test(localUV, p[0], p[1], p[2], p[3]);
|
num_its += cubic_bezier_int_test(localUV, p[0], p[1], p[2], p[3]);
|
||||||
}
|
}
|
||||||
|
@ -1047,43 +1096,45 @@ bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, ou
|
||||||
elementColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex + 1])).rgb, 0);
|
elementColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex + 1])).rgb, 0);
|
||||||
metallicRoughness = head.xy;
|
metallicRoughness = head.xy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return hitElement;
|
||||||
}
|
}
|
||||||
else //Ïß
|
|
||||||
|
bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint pointsOffset, uint styleIndex, float widthHeightRatio,
|
||||||
|
inout vec4 elementColor, inout vec2 metallicRoughness)
|
||||||
{
|
{
|
||||||
|
bool hitElement = false;
|
||||||
float strokeWidth = elementData[styleIndex];
|
float strokeWidth = elementData[styleIndex];
|
||||||
float widthHeightRatio = uintBitsToFloat(currentOffset[4]);
|
|
||||||
|
|
||||||
vec2 size = normalize(vec2(widthHeightRatio, 1)) + vec2(2 * strokeWidth);
|
vec2 size = normalize(vec2(widthHeightRatio, 1)) + vec2(2 * strokeWidth);
|
||||||
vec2 ratio = widthHeightRatio < 1 ? vec2(widthHeightRatio, 1) : vec2(1, 1 / widthHeightRatio);
|
vec2 ratio = widthHeightRatio < 1 ? vec2(widthHeightRatio, 1) : vec2(1, 1 / widthHeightRatio);
|
||||||
localUV *= ratio;
|
localUV *= ratio;
|
||||||
|
|
||||||
|
|
||||||
uint contourIndex = linesOffset + leftChild - 0x80000000;
|
|
||||||
float minDistance = 1e38;
|
float minDistance = 1e38;
|
||||||
uint lineCount = elementIndexs[contourIndex];
|
uint lineCount = elementIndexs[contourIndex];
|
||||||
vec4 styleHead = unpackUnorm4x8(floatBitsToUint(elementData[styleIndex + 1]));
|
vec4 styleHead = unpackUnorm4x8(floatBitsToUint(elementData[styleIndex + 1]));
|
||||||
float lineType = floor(styleHead.b * 10);
|
float lineType = floor(styleHead.b * 10);
|
||||||
//float lineType = 2;
|
int endType = int(round(styleHead.b * 100)) % 10;
|
||||||
vec2 p3Last = vec2(1e38);
|
vec2 p3Last = vec2(1e38);
|
||||||
vec2 p2Last = vec2(1e38);
|
vec2 p2Last = vec2(1e38);
|
||||||
|
vec2 tangentEndLast;
|
||||||
int debugBegin = 0;
|
int debugBegin = 0;
|
||||||
for ( uint contourIterator_ = contourIndex + 1;contourIterator_ <= contourIndex + 1 + lineCount; contourIterator_++)
|
for (uint contourIterator_ = contourIndex + 1; contourIterator_ < contourIndex + 1 + lineCount; contourIterator_++)
|
||||||
{
|
{
|
||||||
uint contourIterator = contourIterator_;
|
uint contourIterator = contourIterator_;
|
||||||
if (contourIterator_ == contourIndex + 1 + lineCount)
|
if (contourIterator_ == contourIndex + 1 + lineCount)
|
||||||
contourIterator = contourIndex + 1;
|
contourIterator = contourIndex + 1;
|
||||||
uint lineIndex = elementIndexs[contourIterator];
|
uint lineIndex = elementIndexs[contourIterator];
|
||||||
uint pLocation = linesOffset + 3 * lineIndex;
|
uint pLocation = linesOffset + 3 * lineIndex;
|
||||||
uvec4 pxIndex = uvec4(pointsOffset)+2*uvec4(elementIndexs[pLocation]>>16, elementIndexs[pLocation]&0xFFFF, elementIndexs[pLocation+1]>>16, elementIndexs[pLocation+1]&0xFFFF);
|
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;
|
uvec4 pyIndex = uvec4(1) + pxIndex;
|
||||||
|
|
||||||
mat4x2 p = mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]],
|
mat4x2 p =
|
||||||
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[2]], elementData[pyIndex[2]], elementData[pxIndex[3]], elementData[pyIndex[3]]);
|
||||||
elementData[pxIndex[3]], elementData[pyIndex[3]]);
|
|
||||||
|
|
||||||
p[0] *= ratio;
|
p[0] *= ratio;
|
||||||
p[1] *= ratio;
|
p[1] *= ratio;
|
||||||
|
@ -1098,52 +1149,61 @@ bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, ou
|
||||||
|
|
||||||
if (distance(localUV, p[0]) <= 0.001)
|
if (distance(localUV, p[0]) <= 0.001)
|
||||||
{
|
{
|
||||||
if(p3Last==p[0]) debugBegin = 2;
|
if (p3Last == p[0])
|
||||||
else debugBegin = 1;
|
debugBegin = 2;
|
||||||
|
else
|
||||||
|
debugBegin = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
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];
|
bool onBegin = distance(localUV, p[0]) <= strokeWidth && ( p3Last == p[0] || contourIterator==contourIndex + 1);
|
||||||
bool fill = true;
|
vec2 tangentBegin;
|
||||||
if(onBegin)
|
vec2 tangentEnd;
|
||||||
{
|
if (p[0] != p[1])
|
||||||
vec2 normalLast = normalize(mat2(0,1,-1,0)*(p3Last-p2Last));
|
tangentBegin = normalize(p[0] - p[1]);
|
||||||
vec2 normalNow = normalize(mat2(0,1,-1,0)*(p[1]-p[0]));
|
else
|
||||||
vec2 normal = normalLast+normalNow;
|
tangentBegin = normalize(p[0] - p[2]);
|
||||||
fill = angleLargeThanPi(normal, localUV-p[0]);
|
if (p[3] != p[2])
|
||||||
}
|
tangentEnd = normalize(p[3] - p[2]);
|
||||||
if(onBegin?fill:d<minDistance)
|
else
|
||||||
|
tangentEnd = normalize(p[3] - p[1]);
|
||||||
|
|
||||||
|
if (onBegin ? shouldFillBeginCap(localUV, percent[0]<1e-5, endType, p[0], tangentBegin, p3Last - p2Last)
|
||||||
|
: d < minDistance)
|
||||||
{
|
{
|
||||||
minDistance = min(minDistance, d);
|
minDistance = min(minDistance, d);
|
||||||
|
|
||||||
bool reverse = p[3].y - p[0].y < 0.;
|
bool reverse = p[3].y - p[0].y < 0.;
|
||||||
|
|
||||||
vec2 tangentBegin = normalize(p[0]-p[1]);
|
if (tangentBegin.y == 0.)
|
||||||
vec2 tangentEnd = normalize(p[3]-p[2]);
|
tangentBegin.y = reverse ? eps : -eps;
|
||||||
if(tangentBegin.y==0.) 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)))
|
||||||
{
|
{
|
||||||
hitElement = true;
|
hitElement = true;
|
||||||
|
// elementColor = vec4(1, 1, 0, 1);
|
||||||
|
vec2 metallicRoughness;
|
||||||
drawLine(minDistance / strokeWidth, styleIndex, elementColor, metallicRoughness);
|
drawLine(minDistance / strokeWidth, styleIndex, elementColor, metallicRoughness);
|
||||||
}
|
}
|
||||||
else if(p3Last==p[0]) hitElement = false;
|
else if (p3Last == p[0])
|
||||||
// if(distance(localUV,p[0])<=strokeWidth&&p3Last==p[0]&&fill)
|
hitElement = false;
|
||||||
// {
|
|
||||||
// hitElement = true;
|
|
||||||
// elementColor = vec4(0,0,1,1);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
tangentEndLast = tangentEnd;
|
||||||
}
|
}
|
||||||
p3Last = p[3];
|
p3Last = p[3];
|
||||||
p2Last = p[2];
|
p2Last = p[2];
|
||||||
}
|
}
|
||||||
|
if (hitElement && distance(localUV, p3Last) <= strokeWidth)
|
||||||
|
{
|
||||||
|
hitElement = shouldFillEndCap(localUV, endType, p3Last, tangentEndLast);
|
||||||
|
}
|
||||||
|
|
||||||
// if (minDistance <= 0.001)
|
// if (minDistance <= 0.001)
|
||||||
// {
|
// {
|
||||||
|
@ -1154,7 +1214,55 @@ bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, ou
|
||||||
// else if (debugBegin == 2)
|
// else if (debugBegin == 2)
|
||||||
// elementColor = vec4(0, 1, 0, 1);
|
// elementColor = vec4(0, 1, 0, 1);
|
||||||
// }
|
// }
|
||||||
|
return hitElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, out vec2 metallicRoughness,
|
||||||
|
inout vec3 debugBVH = vec3(0))
|
||||||
|
{
|
||||||
|
bool hitElement = false;
|
||||||
|
vec4 elementColor = vec4(-1);
|
||||||
|
metallicRoughness = vec2(0, 0.8);
|
||||||
|
|
||||||
|
uint currentOffset[] = elementOffset[elementIndex];
|
||||||
|
uint elementBvhRoot = currentOffset[0];
|
||||||
|
uint styleIndex = currentOffset[1];
|
||||||
|
uint pointsOffset = currentOffset[2];
|
||||||
|
uint linesOffset = currentOffset[3];
|
||||||
|
float widthHeightRatio = uintBitsToFloat(currentOffset[4]);
|
||||||
|
|
||||||
|
elementStack.top = 0;
|
||||||
|
uint elementBvhIndex = 0;
|
||||||
|
uint elementBvhLength = 0x80000000;
|
||||||
|
while (elementBvhIndex < elementBvhLength || !elementStack.empty())
|
||||||
|
{
|
||||||
|
while (elementBvhIndex < elementBvhLength)
|
||||||
|
{
|
||||||
|
vec4 bound = bvhBound[elementBvhRoot + elementBvhIndex];
|
||||||
|
uint leftChild = bvhChildren[elementBvhRoot + elementBvhIndex].x;
|
||||||
|
|
||||||
|
if (all(lessThan(bound.xy, localUV)) && all(lessThan(localUV, bound.zw)))
|
||||||
|
{
|
||||||
|
if (leftChild >= elementBvhLength)
|
||||||
|
{
|
||||||
|
if (any(greaterThan(bound.xy + vec2(0.003), localUV)) ||
|
||||||
|
any(greaterThan(localUV, bound.zw - vec2(0.003))))
|
||||||
|
{
|
||||||
|
debugBVH.g = 0;
|
||||||
|
debugBVH.r += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint contourIndex = linesOffset + leftChild - 0x80000000;
|
||||||
|
bool isFillStyle = elementData[styleIndex] <= 0;
|
||||||
|
if (isFillStyle) // Ãæ
|
||||||
|
{
|
||||||
|
hitElement = fillElement(localUV, contourIndex, linesOffset, pointsOffset, styleIndex,
|
||||||
|
elementColor, metallicRoughness);
|
||||||
|
}
|
||||||
|
else // Ïß
|
||||||
|
{
|
||||||
|
hitElement = strokeElement(localUV, contourIndex, linesOffset, pointsOffset, styleIndex, widthHeightRatio,
|
||||||
|
elementColor, metallicRoughness);
|
||||||
}
|
}
|
||||||
|
|
||||||
elementBvhIndex = elementBvhLength;
|
elementBvhIndex = elementBvhLength;
|
||||||
|
@ -1182,7 +1290,6 @@ bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, ou
|
||||||
return hitElement;
|
return hitElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
ivec2 pixelLocation = ivec2(pixelOffset + gl_GlobalInvocationID.xy);
|
ivec2 pixelLocation = ivec2(pixelOffset + gl_GlobalInvocationID.xy);
|
||||||
|
@ -1195,7 +1302,8 @@ void main()
|
||||||
|
|
||||||
vec3 debugBVH = vec3(0);
|
vec3 debugBVH = vec3(0);
|
||||||
// bool debugHit = false;
|
// bool debugHit = false;
|
||||||
vec4 color = vec4(1,1,1,-1);
|
vec4 color = vec4(0.76, 0.33, 0.15, -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;
|
||||||
|
@ -1221,22 +1329,25 @@ void main()
|
||||||
if (all(lessThan(vec2(-1), localUV)) && all(lessThan(localUV, vec2(1))) && zIndex > color.w)
|
if (all(lessThan(vec2(-1), localUV)) && all(lessThan(localUV, vec2(1))) && zIndex > color.w)
|
||||||
{
|
{
|
||||||
// if (any(greaterThan(bound.xy+vec2(0.005), uv)) || any(greaterThan(uv, bound.zw-vec2(0.005))))
|
// if (any(greaterThan(bound.xy+vec2(0.005), uv)) || any(greaterThan(uv, bound.zw-vec2(0.005))))
|
||||||
if (any(greaterThan(vec2(-1)+vec2(0.005), localUV)) || any(greaterThan(localUV, vec2(1)-vec2(0.005))))
|
if (any(greaterThan(vec2(-1) + vec2(0.005), localUV)) ||
|
||||||
|
any(greaterThan(localUV, vec2(1) - vec2(0.005))))
|
||||||
debugBVH.g += 0.3;
|
debugBVH.g += 0.3;
|
||||||
// uint elementIndex = leftChild - bvhLength;
|
// uint elementIndex = leftChild - bvhLength;
|
||||||
// debugBVH.bg += 0.5 * (localUV + vec2(1));
|
// debugBVH.bg += 0.5 * (localUV + vec2(1));
|
||||||
|
|
||||||
// debugBVH = vec3(0);
|
// debugBVH = vec3(0);
|
||||||
if(flip.x) localUV.x = -localUV.x;
|
if (flip.x)
|
||||||
if(flip.y) localUV.y = -localUV.y;
|
localUV.x = -localUV.x;
|
||||||
|
if (flip.y)
|
||||||
|
localUV.y = -localUV.y;
|
||||||
vec3 elementColor;
|
vec3 elementColor;
|
||||||
vec2 elementMetallicRoughness;
|
vec2 elementMetallicRoughness;
|
||||||
if(drawElement(leftChild - 0x80000000, localUV, scale, elementColor, elementMetallicRoughness, debugBVH))
|
if (drawElement(leftChild - 0x80000000, localUV, scale, elementColor, elementMetallicRoughness,
|
||||||
|
debugBVH))
|
||||||
{
|
{
|
||||||
color = vec4(elementColor, zIndex);
|
color = vec4(elementColor, zIndex);
|
||||||
metallicRoughness = elementMetallicRoughness;
|
metallicRoughness = elementMetallicRoughness;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
index = bvhLength;
|
index = bvhLength;
|
||||||
|
@ -1272,5 +1383,4 @@ void main()
|
||||||
imageStore(gBaseColor, pixelLocation, vec4(debugBVH, 1));
|
imageStore(gBaseColor, pixelLocation, vec4(debugBVH, 1));
|
||||||
imageStore(gMetallicRoughness, pixelLocation, vec4(0, 0.8, 0, 1));
|
imageStore(gMetallicRoughness, pixelLocation, vec4(0, 0.8, 0, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -23,11 +23,6 @@ const std::vector<std::pair<QString, std::function<std::unique_ptr<LayerStyle>()
|
||||||
std::vector<Renderer::BaseStyle> StrokeElementLayerStyle::toBaseStyles() const
|
std::vector<Renderer::BaseStyle> StrokeElementLayerStyle::toBaseStyles() const
|
||||||
{
|
{
|
||||||
std::vector<Renderer::BaseStyle> baseStyles;
|
std::vector<Renderer::BaseStyle> baseStyles;
|
||||||
/*for (auto materialStyle : materialStyles)
|
|
||||||
{
|
|
||||||
baseStyles.push_back(Renderer::BaseStyle(std::make_shared<Renderer::TransformStyle>(),
|
|
||||||
materialStyle));
|
|
||||||
}*/
|
|
||||||
if (enableEachSideIndependent)
|
if (enableEachSideIndependent)
|
||||||
{
|
{
|
||||||
baseStyles.push_back(Renderer::BaseStyle(std::make_shared<Renderer::TransformStyle>(),
|
baseStyles.push_back(Renderer::BaseStyle(std::make_shared<Renderer::TransformStyle>(),
|
||||||
|
@ -37,10 +32,10 @@ std::vector<Renderer::BaseStyle> StrokeElementLayerStyle::toBaseStyles() const
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
strokePair.first->strokeType = Renderer::StrokeType::kBothSides;
|
auto material = std::shared_ptr<MaterialStyle>(std::move(strokePair.first->clone()));
|
||||||
baseStyles.push_back(Renderer::BaseStyle(std::make_shared<Renderer::TransformStyle>(),
|
std::dynamic_pointer_cast<MaterialStyleStroke>(material)->strokeType = Renderer::StrokeType::kBothSides;
|
||||||
strokePair.first));
|
|
||||||
strokePair.first->strokeType = Renderer::StrokeType::kLeftSide;
|
baseStyles.push_back(Renderer::BaseStyle(std::make_shared<Renderer::TransformStyle>(), material));
|
||||||
}
|
}
|
||||||
return baseStyles;
|
return baseStyles;
|
||||||
}
|
}
|
||||||
|
@ -104,31 +99,6 @@ QWidget* StrokeElementLayerStyle::getInputWidget()
|
||||||
this->enableEachSideIndependent = toggled;
|
this->enableEachSideIndependent = toggled;
|
||||||
rightStrokeView->setDisabled(!toggled);
|
rightStrokeView->setDisabled(!toggled);
|
||||||
});
|
});
|
||||||
//auto stroke = std::dynamic_pointer_cast<Renderer::StrokeRadialGradient>(this->materialStyles[0]->materialStroke);
|
|
||||||
//QColor* color = &(stroke->materialMap[1.0].color);
|
|
||||||
/*auto stroke = std::dynamic_pointer_cast<Renderer::StrokePlain>(this->materialStyles[0]->materialStroke);
|
|
||||||
QColor* color = &(stroke->material.color);
|
|
||||||
r->setText(QString::number(color->red()));
|
|
||||||
g->setText(QString::number(color->green()));
|
|
||||||
b->setText(QString::number(color->blue()));
|
|
||||||
QObject::connect(r, &QLineEdit::textChanged, [color](QString content) {
|
|
||||||
if (!content.isEmpty())
|
|
||||||
{
|
|
||||||
color->setRed(content.toInt());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
QObject::connect(g, &QLineEdit::textChanged, [color](QString content) {
|
|
||||||
if (!content.isEmpty())
|
|
||||||
{
|
|
||||||
color->setGreen(content.toInt());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
QObject::connect(b, &QLineEdit::textChanged, [color](QString content) {
|
|
||||||
if (!content.isEmpty())
|
|
||||||
{
|
|
||||||
color->setBlue(content.toInt());
|
|
||||||
}
|
|
||||||
});*/
|
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "../Renderer/Painting/MaterialStyleStroke.h"
|
#include "../Renderer/Painting/MaterialStyleStroke.h"
|
||||||
#include "../Renderer/Painting/MaterialStyleFill.h"
|
#include "../Renderer/Painting/MaterialStyleFill.h"
|
||||||
|
|
||||||
|
using Renderer::MaterialStyle;
|
||||||
using Renderer::MaterialStyleStroke;
|
using Renderer::MaterialStyleStroke;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -62,15 +62,15 @@ QPainterPath PainterPathUtil::monotonization(QPainterPath& painterPath) {
|
||||||
return resPath;
|
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();
|
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() };
|
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 };
|
return { transformToLines(p), ratio };
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ class PainterPathUtil
|
||||||
public:
|
public:
|
||||||
static std::vector<std::vector<Renderer::Point>> transformToLines(const QPainterPath& painterPath);
|
static std::vector<std::vector<Renderer::Point>> transformToLines(const QPainterPath& painterPath);
|
||||||
static QPainterPath monotonization(QPainterPath& painterPath);
|
static QPainterPath monotonization(QPainterPath& painterPath);
|
||||||
static std::pair<QPainterPath, float> normalized(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);
|
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/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 "Painting/MaterialStyleStroke.h"
|
||||||
|
|
||||||
using namespace Renderer;
|
using namespace Renderer;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
@ -156,9 +157,8 @@ std::unique_ptr<Drawable> Model::processMesh(aiMesh* mesh, const aiScene* scene,
|
||||||
|
|
||||||
for (auto& v : vertices)
|
for (auto& v : vertices)
|
||||||
{
|
{
|
||||||
//qDebug() << v.TexCoords.x << v.TexCoords.y;
|
|
||||||
v.TexCoords = (v.TexCoords - leftBottom) / (rightTop - leftBottom);
|
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->vertices = vertices;
|
||||||
|
@ -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[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 });
|
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
|
else
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 1000; i++)
|
for (int i = 0; i < 1000; i++)
|
||||||
|
|
|
@ -105,7 +105,11 @@ std::unique_ptr<MaterialStyle> Renderer::MaterialStyleStroke::clone() const
|
||||||
|
|
||||||
bool Renderer::MaterialStyleStroke::operator==(const MaterialStyle& m) 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
|
float Renderer::MaterialStyleStroke::getHalfWidth() const
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace Renderer
|
||||||
virtual std::unique_ptr<MaterialStyle> clone() const override;
|
virtual std::unique_ptr<MaterialStyle> clone() const override;
|
||||||
virtual bool operator==(const MaterialStyle&) const override;
|
virtual bool operator==(const MaterialStyle&) const override;
|
||||||
float getHalfWidth() const;
|
float getHalfWidth() const;
|
||||||
//protected:
|
|
||||||
float halfWidth;
|
float halfWidth;
|
||||||
StrokeType strokeType;
|
StrokeType strokeType;
|
||||||
StrokeEndType endType;
|
StrokeEndType endType;
|
||||||
|
|
|
@ -12,9 +12,11 @@ Renderer::RendererWidget::RendererWidget(QWidget* parent)
|
||||||
auto openAction = new QAction(QStringLiteral("´ò¿ª"), menu);
|
auto openAction = new QAction(QStringLiteral("´ò¿ª"), menu);
|
||||||
auto saveAction = new QAction(QStringLiteral("±£´æ"), menu);
|
auto saveAction = new QAction(QStringLiteral("±£´æ"), menu);
|
||||||
auto testAction = new QAction(QStringLiteral("²âÊÔ"), menu);
|
auto testAction = new QAction(QStringLiteral("²âÊÔ"), menu);
|
||||||
|
auto test2Action = new QAction(QStringLiteral("²âÊÔ2"), menu);
|
||||||
menu->addAction(openAction);
|
menu->addAction(openAction);
|
||||||
menu->addAction(saveAction);
|
menu->addAction(saveAction);
|
||||||
menu->addAction(testAction);
|
menu->addAction(testAction);
|
||||||
|
menu->addAction(test2Action);
|
||||||
|
|
||||||
ui.openButton->setHaloVisible(false);
|
ui.openButton->setHaloVisible(false);
|
||||||
ui.openButton->setOverlayStyle(::Material::TintedOverlay);
|
ui.openButton->setOverlayStyle(::Material::TintedOverlay);
|
||||||
|
@ -47,7 +49,9 @@ Renderer::RendererWidget::RendererWidget(QWidget* parent)
|
||||||
QObject::connect(testAction, &QAction::triggered, [&] {
|
QObject::connect(testAction, &QAction::triggered, [&] {
|
||||||
ui.openGLWidget->setModel("Models/Sponza/Sponza.gltf");
|
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->setValue(105);
|
||||||
ui.horizontalSlider_2->setValue(80);
|
ui.horizontalSlider_2->setValue(80);
|
||||||
ui.exposureSlider->setValue(60);
|
ui.exposureSlider->setValue(60);
|
||||||
|
|
|
@ -108,6 +108,27 @@ namespace UnitTest
|
||||||
w.show();
|
w.show();
|
||||||
a.exec();
|
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)
|
TEST_CLASS(ElementRendererStokeMaterialTest)
|
||||||
|
|
Loading…
Reference in New Issue