--------------------------------------------------------------------------- -- begin stroke library --------------------------------------------------------------------------- _gStrokeNum = 0 function bezier( b1, b2, b3, b4, t ) local ti = (1.0 - t); local p0 = ti * ti * ti * b1 local p1 = 3*t * ti*ti * b2 local p2 = 3*t*t * ti * b3 local p3 = t*t*t * b4 return p0 + p1 + p2 + p3 end function normalize( x, y ) local dist = bs_distance( x, y ) if dist == 0 then return x,y end return x/dist, y/dist end function stroke_pos( pts, idx ) if idx < 1 then local vx1 = pts[1].x - pts[2].x local vy1 = pts[1].y - pts[2].y local vx2 = pts[2].x - pts[3].x local vy2 = pts[2].y - pts[3].y local a1 = bs_atan( vx1, vy1 ) local a2 = bs_atan( vx2, vy2 ) local adif = a1 - a2 local x,y = bs_rotate( vx1, vy1, adif ) return pts[1].x + x, pts[1].y + y end local s = _gStrokeNum if idx > s then local vx1 = pts[s].x - pts[s-1].x local vy1 = pts[s].y - pts[s-1].y local vx2 = pts[s-1].x - pts[s-2].x local vy2 = pts[s-1].y - pts[s-2].y local a1 = bs_atan( vx1, vy1 ) local a2 = bs_atan( vx2, vy2 ) local adif = a1 - a2 local x,y = bs_rotate( vx1, vy1, adif ) return pts[s].x + x, pts[s].y + y end return pts[idx].x, pts[idx].y end function stroke_width( pts, idx ) if idx < 1 then return pts[1].w end local s = _gStrokeNum if idx > s then return pts[s].w end return pts[idx].w end function stroke_interpolate( pts, t ) local idx = math.floor( t ) local f = t - idx local px4,py4 = stroke_pos( pts, idx+2 ) local px3,py3 = stroke_pos( pts, idx+1 ) local px2,py2 = stroke_pos( pts, idx+0 ) local px1,py1 = stroke_pos( pts, idx-1 ) local vx2 = px4 - px2 local vy2 = py4 - py2 local vx1 = px3 - px1 local vy1 = py3 - py1 local len = bs_distance( px3-px2, py3-py2 ) local m = 0.35 vx1,vy1 = normalize( vx1, vy1 ) vx1 = vx1 * len * m vy1 = vy1 * len * m vx2,vy2 = normalize( vx2, vy2 ) vx2 = vx2 * len * m vy2 = vy2 * len * m local cx1 = pts[idx].x + vx1 local cy1 = pts[idx].y + vy1 local cx2 = pts[idx+1].x - vx2 local cy2 = pts[idx+1].y - vy2 local x = bezier( px2, cx1, cx2, px3, f ) local y = bezier( py2, cy1, cy2, py3, f ) local w1 = stroke_width( pts, idx ) local w2 = stroke_width( pts, idx+1 ) local w = w1 + (w2 - w1) * f return x,y,w end function stroke_normal( x_, x, y_, y, w ) local nx = x_ - x local ny = y_ - y nx,ny = normalize( nx, ny ) nx,ny = bs_rotate( nx, ny, 3.14159/2 ) return nx*w/2, ny*w/2 end function stroke_subdiv( pts, idx ) local x1,y1,w1 = stroke_interpolate( pts, idx + 0.0 ) local x2,y2,w2 = stroke_interpolate( pts, idx + 0.25 ) local x3,y3,w3 = stroke_interpolate( pts, idx + 0.50 ) local x4,y4,w4 = stroke_interpolate( pts, idx + 0.75 ) local x5,y5,w5 = stroke_interpolate( pts, idx + 0.999 ) local dist = 0 dist = dist + bs_distance( x2-x1, y2-y1 ) dist = dist + bs_distance( x3-x2, y3-y2 ) dist = dist + bs_distance( x4-x3, y4-y3 ) dist = dist + bs_distance( x5-x4, y5-y4 ) local subdiv = dist / 4 if subdiv < 16 then subdiv = 16 end if subdiv > 128 then subdiv = 128 end return subdiv end function stroke_add( pts, x, y, w ) local idx = _gStrokeNum + 1 pts[idx] = {} pts[idx].x = x pts[idx].y = y pts[idx].w = w _gStrokeNum = _gStrokeNum + 1 end function stroke_set( pts ) local s = _gStrokeNum if s < 3 then return end local x,y,w = stroke_interpolate( pts, 1 ) local x_,y_,w_ = stroke_interpolate( pts, 1 + 0.0001 ) local nx,ny = stroke_normal( x_, x, y_, y, w ) bs_polygon( pts[1].x + nx, pts[1].y + ny ) -- side 1 local i,j for i=1,s-1 do local subdiv = math.floor( stroke_subdiv( pts, i ) ) for j=1,subdiv-1 do x,y,w = stroke_interpolate( pts, i + j/subdiv ) x_,y_,w_ = stroke_interpolate( pts, i + j/subdiv + 1/1000 ) nx,ny = stroke_normal( x_, x, y_, y, w ) bs_polygon( x + nx, y + ny ) end end x,y,w = stroke_interpolate( pts, s-1 + 0.999 ) x_,y_,w_ = stroke_interpolate( pts, s-1 + 0.9991 ) nx,ny = stroke_normal( x_, x, y_, y, w ) bs_polygon( pts[s].x + nx, pts[s].y + ny ) -- side 2 bs_polygon( pts[s].x - nx, pts[s].y - ny ) for i=1,s-1 do local idx = s+1 - i local subdiv = math.floor( stroke_subdiv( pts, idx-1 ) ) for j=1,subdiv-1 do x,y,w = stroke_interpolate( pts, idx - j/subdiv ) x_,y_,w_ = stroke_interpolate( pts, idx - j/subdiv - 1/1000 ) nx,ny = stroke_normal( x_, x, y_, y, w ) bs_polygon( x + nx, y + ny ) end end x,y,w = stroke_interpolate( pts, 1 + 0.001 ) x_,y_,w_ = stroke_interpolate( pts, 1 ) nx,ny = stroke_normal( x_, x, y_, y, w ) bs_polygon( pts[1].x + nx, pts[1].y + ny ) _gStrokeNum = 0 end --------------------------------------------------------------------------- -- end stroke library --------------------------------------------------------------------------- function default_size() return 50, 0.5 end function param1() return "密度", 1, 100, 30 end function param2() return "色ランダム", 0, 100, 40 end function param3() return "カーブ", 5, 100, 20 end function main( x, y, p ) local w = bs_width() if w < 10 then w = 10 end if not firstDraw then local distance = bs_distance( lastDrawX - x, lastDrawY - y ) if distance < w*0.8 then return 0 end end local dx,dy = bs_dir() local pts = {} local m = w * 0.7 local num = 10 * bs_param1() / 100 local ang = bs_param3() / 100 * 3.14 * 4 local i for i=0,num do local dx = 0 local dy = 0 local vx,vy = bs_rotate( m, 0, (0.5-math.random()) * ang ) dx = dx + vx dy = dy + vy stroke_add( pts, dx,dy, 0 ) local vx,vy = bs_rotate( m, 0, (0.5-math.random()) * ang ) dx = dx + vx dy = dy + vy stroke_add( pts, dx,dy, w * (0.5 + math.random()*0.5)/10 ) local vx,vy = bs_rotate( m, 0, (0.5-math.random()) * ang ) dx = dx + vx dy = dy + vy stroke_add( pts, dx,dy, w * (0.5 + math.random()*0.5)/10 ) local vx,vy = bs_rotate( m, 0, (0.5-math.random()) * ang ) dx = dx + vx dy = dy + vy stroke_add( pts, dx,dy, w * (0.5 + math.random()*0.5)/10 ) local vx,vy = bs_rotate( m, 0, (0.5-math.random()) * ang ) dx = dx + vx dy = dy + vy stroke_add( pts, dx,dy, 0 ) stroke_set( pts ) bs_polygon_move_center() bs_polygon_rotate( 3.14*2* math.random() ) bs_polygon_move( x + w*(0.5-math.random())/1.5, y + w*(0.5-math.random())/1.5 ) local r,g,b = bs_forebg( 1.0 - math.random()*bs_param2()/100 ) bs_fill( r,g,b, 255 ) end lastDrawX = x lastDrawY = y firstDraw = false return 1 end lastDrawX = 0 lastDrawY = 0 firstDraw = true