1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
|
// ----------------------------------------------------------------------------
// Copyright (c) 2014, Nicolas P. Rougier. All Rights Reserved.
// Distributed under the (new) BSD License.
// ----------------------------------------------------------------------------
#include "arrows/util.glsl"
/* ---------------------------------------------------------
Computes the signed distance to an curved arrow
Parameters:
-----------
texcoord : Point to compute distance to
body : Total length of the arrow (pixels, body+head)
head : Length of the head (pixels)
height : Height of the head (pixel)
linewidth: Stroke line width (in pixels)
antialias: Stroke antialiased area (in pixels)
Return:
-------
Signed distance to the arrow
--------------------------------------------------------- */
float arrow_curved(vec2 texcoord,
float body, float head,
float linewidth, float antialias)
{
float w = linewidth/2.0 + antialias;
vec2 start = -vec2(body/2.0, 0.0);
vec2 end = +vec2(body/2.0, 0.0);
float height = 0.5;
vec2 p1 = end - head*vec2(+1.0,+height);
vec2 p2 = end - head*vec2(+1.0,-height);
vec2 p3 = end;
// Head : 3 circles
vec2 c1 = circle_from_2_points(p1, p3, 1.25*body).zw;
float d1 = length(texcoord - c1) - 1.25*body;
vec2 c2 = circle_from_2_points(p2, p3, 1.25*body).xy;
float d2 = length(texcoord - c2) - 1.25*body;
vec2 c3 = circle_from_2_points(p1, p2, max(body-head, 1.0*body)).xy;
float d3 = length(texcoord - c3) - max(body-head, 1.0*body);
// Body : 1 segment
float d4 = segment_distance(texcoord, start, end - vec2(linewidth,0.0));
// Outside (because of circles)
if( texcoord.y > +(2.0*head + antialias) )
return 1000.0;
if( texcoord.y < -(2.0*head + antialias) )
return 1000.0;
if( texcoord.x < -(body/2.0 + antialias) )
return 1000.0;
if( texcoord.x > c1.x ) //(body + antialias) )
return 1000.0;
return min( d4, -min(d3,min(d1,d2)));
}
|