Skip to content

Instantly share code, notes, and snippets.

@termat
Created February 28, 2019 13:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save termat/0b5be41b092a2a477dbee6ec3eca2cc2 to your computer and use it in GitHub Desktop.
Save termat/0b5be41b092a2a477dbee6ec3eca2cc2 to your computer and use it in GitHub Desktop.
Inverse Kinematics Fiber
<html>
<head>
<meta charset="UTF-8" />
<title>Inverse Kinematics Fiber</title>
</head>
<body>
<meta name="viewport" content="width=460, user-scalable=no, maximum-scale=1.0">
<script id="processing-code" type="application/processing">
Tail tail;
void setup() {
size(400,400);
tail=new Tail();
frameRate(30);
}
void draw() {
background(255);
int mx=mouseX;
int my=mouseY;
if(tx!=-999&&ty!=-999){
mx=tx;
my=ty;
}
for(int i=0;i<tail.num;i++){
IKLine ll=(IKLine)tail.lines.get(i);
ll.nextFrame(mx,my);
drawIKLine(ll);
}
}
void drawIKLine(IKLine ll){
stroke(ll.col);
ArrayList segs=ll.segs;
float len=ll.segLen;
for(int i=1;i<segs.size();i++){
Seg sa=(Seg)segs.get(i-1);
Seg sb=(Seg)segs.get(i);
line(sa.x,sa.y,sb.x,sb.y);
}
}
class Tail{
int num=50;
ArrayList lines;
public Tail(){
lines=new ArrayList();
for(int i=0;i<num;i++){
float rr=random(1.0)*10;
float rad=random(1.0)*PI*2;
IKLine line=new IKLine();
line.x=cos(rad)*rr;
line.y=sin(rad)*rr;
line.friction=random(1.0)*0.2+0.7;
line.col=#334422;
lines.add(line);
}
}
}
class Seg{
float len;
float x;
float y;
float vx;
float vy;
float pvx=0;
float pvy=0;
float rot;
public Seg(float l){
len=l;
}
public void next(){
x +=vx;
y +=vy;
}
public void setVector(){
vx=x-pvx;
vy=y-pvy;
pvx=x;
pvy=y;
}
public float[] getPin(){
float[] ret=new float[2];
ret[0]=x+cos(rot)*len;
ret[1]=y+sin(rot)*len;
return ret;
}
}
class IKLine{
ArrayList segs=new ArrayList();
float x;
float y;
float segLen=30;
int segNum=8;
float grav=0;
float friction=1.0;
color col=#888888;
public IKLine(){
segs.add(new Seg(0.0));
for(int i=1;i<segNum;i++){
Seg s=new Seg(segLen-0.5*i);
segs.add(s);
}
}
public void drag(Seg se,float px,float py){
se.next();
float dx=px-se.x;
float dy=py-se.y;
se.rot=atan2(dy,dx);
float[] pin=se.getPin();
float w=pin[0]-se.x;
float h=pin[1]-se.y;
se.x=px-w;
se.y=py-h;
se.setVector();
se.vx *=friction;
se.vy *=friction;
se.vy +=grav;
}
public void nextFrame(int px,int py){
drag((Seg)segs.get(0),px,py);
for(int i=1;i<segNum;i++){
Seg sa=(Seg)segs.get(i);
Seg sb=(Seg)segs.get(i-1);
drag(sa,sb.x,sb.y);
}
}
}
</script>
<table border="1"><tr><td>
<canvas id="canvas" width="400" height="400"></canvas>
</td></tr></table>
</body>
</html>
var tx=-999;
var ty=-999;
function touchDown(event) {
tx=event.touches[0].pageX;
ty=event.touches[0].pageY;
event.preventDefault();
};
function touchMove(event) {
tx=event.touches[0].pageX;
ty=event.touches[0].pageY;
event.preventDefault();
};
function touchUp(event) {
tx=-999;
ty=-999;
event.preventDefault();
};
$(document).ready(function(){
var canvas = document.getElementById('canvas');
canvas.addEventListener("touchstart", touchDown, false);
canvas.addEventListener("touchmove", touchMove, false);
canvas.addEventListener("touchend", touchUp, false);
var codeElm = document.getElementById('processing-code');
var code = codeElm.textContent || codeElm.innerText;
new Processing(canvas, code);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/processing.js/1.6.6/processing.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
body { background-color: #DDDDDD; font: 30px sans-serif; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment