Skip to content

Instantly share code, notes, and snippets.

@mwmwmw
Created October 16, 2019 22:24
Show Gist options
  • Save mwmwmw/617150a2d51e8e966c9359d14c4cab45 to your computer and use it in GitHub Desktop.
Save mwmwmw/617150a2d51e8e966c9359d14c4cab45 to your computer and use it in GitHub Desktop.
A basic line with distance collider. It's called a pill collider because of the pill shape it.
import { Vector3, Object3D, BufferGeometry, Math as M, Group, LineBasicMaterial, Line, Line3, CylinderBufferGeometry, BufferAttribute, SphereBufferGeometry } from "three";
export function Pill(start, end, radius) {
Object3D.call(this);
this.radius = radius;
this.type = "Pill";
this._start = start;
this._end = end;
var geometry = new BufferGeometry();
var line = new BufferGeometry();
this.line = line;
this.geometry = geometry;
var vertices = new Float32Array([
start.x,
start.y,
start.z,
end.x,
end.y,
end.z
]);
this.line.addAttribute("position", new BufferAttribute(vertices, 3));
this.delta = function(target = new Vector3()) {
return target.copy(this.end).sub(this.start);
};
Object.defineProperty(this, "start", {
get: function() {
var arr = line.attributes.position.array;
return this.localToWorld(this._start.set(arr[0], arr[1], arr[2]));
}
});
Object.defineProperty(this, "end", {
get: function() {
var arr = line.attributes.position.array;
return this.localToWorld(this._end.set(arr[3], arr[4], arr[5]));
}
});
}
Pill.prototype = Object.assign(Object.create(Object3D.prototype), {
constructor: Pill
});
export function PillHelper(pill) {
Object3D.call(this);
this.type = "PillHelper";
this.pill = pill;
var start = pill.start;
var end = pill.end;
var radius = pill.radius;
var cylinder = new CylinderBufferGeometry( radius, radius, start.distanceTo(end), 8,1, false );
var sphere = new SphereBufferGeometry( radius, 8, 4 );
var sphere2 = new SphereBufferGeometry( radius, 8, 4 );
sphere.translate(0,-start.distanceTo(end)*0.5,0);
sphere2.translate(0,start.distanceTo(end)*0.5,0);
this.material = new LineBasicMaterial({ color: Math.random() * 0xffffff });
var l3 = new Line3(start, end);
var center = l3.getCenter(new Vector3())
this.group = new Group();
this.group.add(new Line(sphere, this.material));
this.group.add(new Line(sphere2, this.material));
this.group.add(new Line(cylinder, this.material));
this.group.position.copy(center);
this.group.lookAt(start);
this.group.rotateX(M.degToRad(90))
this.add(this.group)
this.update = function () {
this.position.copy(this.pill.position);
this.rotation.copy(this.pill.rotation);
this.scale.copy(this.pill.scale)
}
this.update();
}
PillHelper.prototype = Object.assign(Object.create(Object3D.prototype), {
constructor: PillHelper
});
function clamp(n = 0, min = 0, max = 1) {
if (n < min) return min;
if (n > max) return max;
return n;
}
export function testPill(pill1, pill2, c1 = new Vector3(), c2 = new Vector3()) {
var dist = closestPoint(pill1, pill2, c1, c2);
var radius = pill1.radius + pill2.radius;
//console.log(dist, radius * radius);
return dist <= radius * radius;
}
var d1a = new Vector3();
var d2a = new Vector3();
export function closestPoint(line1, line2, c1 = new Vector3(), c2 = new Vector3()) {
var d1 = line1.delta(d1a);
var d2 = line2.delta(d2a);
var r = line1.start.clone().sub(line2.start);
var a = d1.dot(d1);
var e = d2.dot(d2);
var f = d2.dot(r);
var s = 0;
var t = 0;
if (a <= Number.EPSILON && e <= Number.EPSILON) {
var s = 0;
var t = 0;
c1.copy(line1.start);
c2.copy(line2.start);
var dist = c1.clone().sub(c2);
return dist.dot(dist);
}
if (a <= Number.EPSILON) {
s = 0;
t = f / e;
t = clamp(t);
} else {
var c = d1.clone().dot(r);
if (e <= Number.EPSILON) {
t = 0;
s = clamp(-c / a);
} else {
var b = d1.clone().dot(d2);
var denom = a * e - b * b;
if (denom != 0) {
s = clamp((b * f - c * e) / denom);
} else {
s = 0;
}
t = (b * s + f) / e;
if (t < 0) {
t = 0;
s = clamp(-c / a);
} else if (t > 1) {
t = 1;
s = clamp((b - c) / a);
}
}
}
c1.copy(line1.start.clone().add(d1.multiplyScalar(s)));
c2.copy(line2.start.clone().add(d2.multiplyScalar(t)));
var dist = c1.clone().sub(c2);
return dist.dot(dist);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment