Created
October 21, 2012 15:22
-
-
Save xl1/3927259 to your computer and use it in GitHub Desktop.
ゴルフのやつ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://jsdo.it/xl1/aTTK | |
#define REFLECT_MAX 10 | |
#define NODE_LEN 10 | |
precision mediump float; | |
struct Segment { | |
vec2 start; | |
vec2 dir; | |
float len; | |
}; | |
struct Circle { | |
vec2 center; | |
float radius; | |
}; | |
struct Intersect { | |
float at; | |
vec2 edge; | |
}; | |
const vec4 border = vec4(300.0, 170.0, 0.0, 100.0); | |
const vec2 handleSize = vec2(20.0, 20.0); | |
const vec2 origin = vec2(200.0, 300.0); | |
uniform vec2 u_textureSize; | |
varying vec2 v_texCoord; | |
uniform float timing; | |
vec2 nodes(int idx){ | |
if(idx == 1) return vec2(160.0, 180.0); | |
if(idx == 2) return vec2( 80.0, 180.0); | |
if(idx == 3) return vec2( 30.0, 100.0); | |
if(idx == 4) return vec2( 20.0, 20.0); | |
if(idx == 5) return vec2( 90.0, 20.0); | |
if(idx == 6) return vec2( 90.0, 115.0); | |
if(idx == 7) return vec2(180.0, 115.0); | |
if(idx == 8) return vec2(250.0, 170.0); | |
if(idx == 9) return vec2(240.0, 300.0); | |
return vec2(160.0, 300.0); | |
} | |
Intersect intersectSegments(Segment a, Segment b){ | |
vec2 start = b.start - a.start; | |
vec3 prod = cross( | |
vec3(a.dir.x, b.dir.x, start.x), | |
vec3(a.dir.y, b.dir.y, start.y) | |
); | |
if(abs(prod.z) > 1e-6){ | |
float ratioA = -prod.x / prod.z; | |
float ratioB = prod.y / prod.z; | |
if(0.0 < ratioA && ratioA < a.len && 0.0 < ratioB && ratioB < b.len){ | |
return Intersect(ratioA - 1e-4, b.dir); | |
} | |
} | |
return Intersect(a.len, vec2(0.0)); | |
} | |
Intersect intersectCircle(Segment a, Circle c){ | |
vec2 cstart = c.center - a.start; | |
vec2 cend = c.center - (a.start + a.len * a.dir); | |
float dist = abs(a.dir.x * cstart.y - a.dir.y * cstart.x); | |
float pstart = dot(a.dir, cstart); | |
float pend = dot(a.dir, cend); | |
if(dist < c.radius && pstart * pend < 0.0){ | |
float at = pstart - sqrt(c.radius * c.radius - dist * dist); | |
return Intersect(at, normalize(at * a.dir - c.center).yx * vec2(-1.0, 1.0)); | |
} | |
return Intersect(a.len, vec2(0.0)); | |
} | |
bool inField(vec2 pos){ | |
bool result = false; | |
Segment ray = Segment(pos, vec2(1.0, 0.0), 400.0); | |
for(int i = 0; i < NODE_LEN; i++){ | |
vec2 ed = nodes(i+1) - nodes(i); | |
Segment edge = Segment(nodes(i), normalize(ed), length(ed)); | |
Intersect isc = intersectSegments(ray, edge); | |
if(isc.at < ray.len) result = !result; | |
} | |
return result; | |
} | |
bool inArrow(vec2 pos, Segment arrow){ | |
vec2 p = pos - arrow.start; | |
float xprod = abs(arrow.dir.x * p.y - arrow.dir.y * p.x); | |
float dprod = dot(arrow.dir, p); | |
if(dprod < 0.0 || arrow.len < dprod) return false; | |
if(dprod > arrow.len * 0.2){ | |
return xprod < 0.06 * arrow.len; | |
} else { | |
return xprod < 0.6 * length(p); | |
} | |
} | |
bool inCircle(vec2 pos, Circle circle){ | |
return distance(pos, circle.center) < circle.radius; | |
} | |
bool chase(inout Segment loc, Circle goal){ | |
for(int j = 0; j < REFLECT_MAX; j++){ | |
Intersect isc = Intersect(loc.len, vec2(0.0)); | |
for(int i = 0; i < NODE_LEN; i++){ | |
vec2 ed = nodes(i+1) - nodes(i); | |
Segment edge = Segment(nodes(i), normalize(ed), length(ed)); | |
Intersect iscLocal = intersectSegments(loc, edge); | |
if(iscLocal.at < isc.at) isc = iscLocal; | |
} | |
Intersect iscgoal = intersectCircle(loc, goal); | |
if(iscgoal.at < isc.at){ | |
loc.start += loc.dir * iscgoal.at; | |
loc.dir = normalize(goal.center - loc.start); | |
loc.len = distance(goal.center, loc.start); | |
return true; | |
} | |
loc.len -= isc.at; | |
loc.start += loc.dir * isc.at; | |
loc.dir = 2.0 * dot(loc.dir, isc.edge) * isc.edge - loc.dir; | |
} | |
return false; | |
} | |
void main(){ | |
vec2 handle = u_textureSize - vec2(border[1], border[2]) - (handleSize * 0.5) - origin; | |
vec2 position = v_texCoord * u_textureSize; | |
Circle goal = Circle(vec2(50.0, 40.0), 12.0); | |
if(timing == 0.0){ | |
Segment arrow = Segment( | |
origin, | |
normalize(handle), | |
length(handle) | |
); | |
if(inArrow(position, arrow)){ | |
gl_FragColor = vec4(0.9, 0.1, 0.1, 1.0); | |
return; | |
} | |
} | |
Segment loc = Segment( | |
origin, | |
-normalize(handle), | |
length(handle) * timing | |
); | |
bool goaled = chase(loc, goal); | |
if(!goaled && distance(loc.start, position) < 6.0){ | |
gl_FragColor = vec4(0.9, 0.9, 0.9, 1.0); | |
} else if(inCircle(position, goal)){ | |
if(goaled){ | |
gl_FragColor = vec4(0.2, 0.9, 0.5, 1.0); | |
} else { | |
gl_FragColor = vec4(0.4, 0.0, 0.0, 1.0); | |
} | |
} else if(inField(position)) { | |
gl_FragColor = vec4(0.3, 0.6, 0.2, 1.0); | |
} else if(position.x < 270.0 && position.y < 310.0) { | |
gl_FragColor = vec4(0.9, 0.7, 0.4, 1.0); | |
} else { | |
gl_FragColor = vec4(0.0); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
attribute vec4 a_position; | |
attribute vec2 a_texCoord; | |
uniform mat4 u_projectionMatrix; | |
varying vec2 v_texCoord; | |
void main(){ | |
v_texCoord = a_texCoord; | |
gl_Position = u_projectionMatrix * a_position; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment